Modèle d'autorité du serveur

*Ce contenu est traduit en utilisant l'IA (Beta) et peut contenir des erreurs. Pour consulter cette page en anglais, clique ici.

Dans un modèle d'autorité du serveur, le serveur est la seule source de vérité pour l'état du jeu entier, et les clients ne sont que dignes de confiance pour rapporter leurs propres entrées. Cette architecture est la base du netcode d'un jeu compétitif équitable car elle empêche des classes entières de triche, comme les flyhacks ou les speedhacks, en ne faisant jamais confiance à un client pour rapporter sa propre position ou état.

Avantages

Dans un système naïf possédé par le serveur, les clients enverraient simplement leurs entrées au serveur et afficheraient les résultats du jeu renvoyés par le serveur. Bien que techniquement correct, un tel système ferait face à une latence d'entrée significative car chaque action de joueur devrait voyager jusqu'au serveur, être traitée, et avoir le résultat renvoyé au client avant de pouvoir être affichée. Pour la plupart des jeux, en particulier ceux à rythme rapide, ce délai aller-retour ferait que le gameplay semblerait lent, non réactif et injouable.

Dans le modèle d'autorité du serveur de Roblox, la latence est compensée en permettant aux clients de prédire instantanément les effets de leurs entrées en plus de les envoyer au serveur. Par exemple, lorsqu'un joueur appuie sur une touche, le client n'attend pas que le serveur réponde ; au lieu de cela, il prédit quelques images à l'avance de l'état du serveur connu. Cela permet au client d'afficher instantanément le résultat de l'action d'entrée, masquant efficacement la latence réseau et rendant le jeu réactif.

Parfois, le client se trompe dans sa prédiction (misprediction) et, en raison de la latence réseau, le client ne saura pas qu'il a fait une erreur pendant quelques images. Par exemple :

Lorsqu'une erreur de prédiction est détectée, le client doit corriger sa prédiction en fonction de l'état autoritaire du serveur. Si l'état autoritaire est différent de l'état prédit par le client, le client doit revenir en arrière et resimuler ses images prédites. Ce système de prédiction côté client, de retour en arrière et de resimulation est connu sous le nom de "compensation de latence" et aide à rendre les jeux multijoueurs autoritaires par le serveur fluides et réactifs.

Configuration

Le modèle d'autorité du serveur nécessite certaines autres technologies du moteur pour fonctionner correctement. Confirmez les paramètres de propriété suivants sur l'objet Workspace dans l'Explorateur :

  1. Workspace.AuthorityMode doit être Server (le fait de définir cela définit automatiquement les cinq suivants).
  2. Workspace.UseFixedSimulation doit être activé.
  3. Workspace.StreamingEnabled doit être activé.

Concepts

Le système d'autorité du serveur repose sur quelques concepts clés comme suit.

Prédiction client

Grâce à la prédiction client, le client simule quelques images à l'avance de l'état du serveur connu pour prédire immédiatement les effets des entrées des joueurs. Cela masque la latence d'entrée, mais la prédiction peut s'avérer incorrecte par la suite (mauvaise prédiction du client) et nécessiter une correction. Le client essaie de simuler juste assez loin devant l'état autoritaire du serveur connu pour que ses entrées arrivent sur le serveur à l'image prévue. Le nombre d'images que le client prédira à l'avance de l'état du serveur connu est basé sur la latence entre le client et le serveur.

Mauvaise prédiction du client

Lorsque le client reçoit l'état autoritaire du serveur, il vérifie cet état par rapport à un enregistrement historique de ce qu'il a prédit localement pour cette image. Lorsqu'il y a une différence entre ce que le client a prédit et ce que le serveur a réellement fait, c'est une mauvaise prédiction. Les mauvaises prédictions peuvent se produire pour plusieurs raisons, y compris des variations de latence réseau, d'autres joueurs agissant de manière que le client n'avait pas anticipée, le jeu exécutant certaines logiques exclusivement sur le serveur, etc.

Si l'état autoritaire est différent de l'état prédit par le client, le client doit revenir en arrière et resimuler.

Retour en arrière et resimulation

Lorsqu'un client détecte une mauvaise prédiction, il doit se réinitialiser à l'état autoritaire du serveur, puis resimuler pour revenir à son image prédite. En fonction de la latence réseau, le client essaie de simuler juste assez loin devant l'état autoritaire du serveur connu pour que ses entrées arrivent sur le serveur à l'image prévue.

Dans le diagramme ci-dessus, le client simule 2 images à l'avance du serveur. Il envoie ses entrées pour l'image 3 qui arrivent à l'image prévue (3) sur le serveur. Le serveur envoie l'état autoritaire pour l'image 3 et le client le reçoit à l'image 7. Le client découvre qu'il a mal prédit l'image 3, donc il se réinitialise à l'image 3 du serveur et resimule les images 4, 5 et 6 avant de simuler l'image 7. Les joueurs peuvent voir un artefact réseau notable tel qu'un mouvement soudain.

En résumé, le client :

  1. Reçoit l'état autoritaire du serveur et le compare à son propre état prédit.
  2. Si la prédiction du client était incorrecte :
    1. Le client revient à l'état autoritaire connu reçu du serveur.
    2. Le client resimule de l'état autoritaire à son état prédit, réappliquant toutes les entrées locales.

Mise en œuvre

Propriété réseau et prédiction

Dans le modèle d'autorité du serveur, vous pouvez garder les objets de gameplay principaux possédés par le serveur sans encourir le coût de latence d'entrée normalement associé à la propriété du serveur. Des choses comme des voitures, des personnages joueurs ou d'autres objets critiques pour le gameplay peuvent rester possédés par le serveur, même lorsqu'ils interagissent avec d'autres joueurs.

Par défaut, Roblox prédit automatiquement les propriétés avec accès à la simulation près du joueur local Character, mais si vous souhaitez un contrôle plus précis, vous pouvez forcer explicitement la prédiction d'une instance à activer ou désactiver avec RunService:SetPredictionMode().

La prédiction automatique s'applique à des ensembles de physique entiers, pas à des instances individuelles. Lorsque le client prédit une pièce, il prédit également chaque pièce qui est physiquement connectée à elle par des soudures, des joints ou des contraintes, ainsi que le parent Model de ces pièces et tout Humanoid à l'intérieur de ce modèle. Par exemple :

  • Un modèle d'épée qui est soudé à un personnage prédit devient partie de l'assemblage du personnage, donc il est prédit automatiquement.
  • Un modèle qui est parenté au personnage mais non physiquement connecté à lui est un assemblage séparé. Il n'est prédit que s'il est dans le rayon de simulation du client ou si vous forcez la prédiction avec RunService:SetPredictionMode().

Pour vérifier si une instance spécifique est actuellement prédite, appelez RunService:GetPredictionStatus() depuis le client.

Synchronisation de simulation

Dans le modèle d'autorité du serveur, le client et le serveur doivent tous deux exécuter la simulation principale, et la simulation du client doit pouvoir revenir en arrière et resimuler lorsqu'une mauvaise prédiction se produit. Pour activer cela, écrivez votre logique principale à l'intérieur de fonctions liées via RunService:BindToSimulation() dans un ModuleScript qui est initialisé à la fois sur le client et le serveur.

Configuration de l'autorité du serveur

Lors d'une resimulation, Roblox réexécutera les fonctions liées à la simulation via BindToSimulation(). Le traitement des entrées des joueurs, l'interaction avec des objets physiques synchronisés et la mise à jour de l'état de jeu principal devraient se faire à l'intérieur de ces fonctions liées.

Utilisez time() pour toute logique basée sur le temps à l'intérieur d'une fonction de simulation liée, comme conduire une vitesse d'animation ou faire osciller une valeur dans le temps. Lorsque Workspace.AuthorityMode est Enum.AuthorityMode.Server, time() est synchronisé entre le client et le serveur et utilise un temps de simulation à pas fixe. Pendant la resimulation, il revient à l'image autoritaire et avance à mesure que le client rejoue les images, donc il renvoie une valeur cohérente chaque fois qu'une image est simulée.

ModuleScript nommé Simulation dans ReplicatedStorage :

Simulation
local RunService = game:GetService("RunService")
local Players = game:GetService("Players")
local Simulation = {}
Simulation.Initialize = function()
RunService:BindToSimulation(function(deltaTime)
-- Lire les entrées des joueurs
-- Mettre à jour l'état du jeu
end)
end
return Simulation

Synchronisation d'état avec des attributs

Roblox synchronise automatiquement toutes les propriétés avec accès à la simulation sur les instances prédites. Pour les données personnalisées, les attributs sont le principal moyen de synchroniser les instances marquées comme prédites ; sur ces instances, toute discordance dans les valeurs d'attribut entre la source de vérité du serveur et la prédiction du client déclenchera un retour en arrière et resimulation complet.

Limites des attributs

Pour être répliqué, un attribut doit répondre à tous les critères suivants :

  • Il fait partie des 64 premiers attributs sur son Instance.
  • Son nom contient au maximum 50 caractères.
  • Si un attribut de type chaîne, sa valeur contient au maximum 50 caractères.

Accès à la simulation

De nombreuses propriétés et méthodes dans la référence API du moteur incluent l'étiquette Accès à la Simulation, par exemple BasePart.CFrame. Les propriétés avec cette étiquette seront prédites par le système d'autorité du serveur. De plus, seules les propriétés et méthodes avec cette étiquette peuvent être accessibles à l'intérieur de fonctions liées avec RunService:BindToSimulation().

Créer et supprimer des instances

À l'intérieur de fonctions liées via BindToSimulation(), vous pouvez créer des instances avec Instance.new(), Instance:Clone(), ou Instance.fromExisting(). Le client crée l'instance immédiatement, et Roblox la fusionne avec la copie autoritaire du serveur lorsque cette copie arrive. Pour plus de détails, voir création d'instance prédictive.

La suppression d'instances fonctionne différemment. Instance:Destroy() n'a pas d'accès à la simulation, et vous ne pouvez pas changer le Parent d'une instance qui est déjà dans le DataModel, donc appeler l'un ou l'autre à l'intérieur d'une fonction liée provoque une erreur. Au lieu de cela, enregistrez l'intention de supprimer une instance dans un attribut à l'intérieur de la simulation, puis supprimez l'instance en dehors de la simulation, par exemple dans une connexion PostSimulation sur le serveur.

Script Serveur - Supprimer une Instance En Dehors de la Simulation
local RunService = game:GetService("RunService")
local character = script.Parent
RunService.PostSimulation:Connect(function()
-- "SwordEquipped" est écrit par la simulation lorsque le joueur déséquipe l'épée
local sword = character:FindFirstChild("Sword")
if sword and not character:GetAttribute("SwordEquipped") then
sword:Destroy()
end
end)

Actions d'entrée

Dans un jeu autoritaire par le serveur, le principal moyen pour un client d'affecter l'état du jeu est à travers le Système d'Action d'Entrée. Ces entrées sont envoyées au serveur et sont rejouées lors de la resimulation sur le client. En conséquence, InputActions doit être utilisé pour toutes les entrées qui affectent la simulation principale et elles doivent être vérifiées pour leur validité avant d'être traitées.

Notez que InputContexts doit être un descendant d'un Player afin que le moteur sache qui a la propriété sur le InputContext. Une approche consiste à ajouter vos InputContexts à un dossier sous ReplicatedStorage et à utiliser un Script sous ServerScriptService pour cloner le InputContexts par joueur :

InputSetup
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local InputsFolder = ReplicatedStorage:WaitForChild("Inputs")
local function onPlayerAdded(player)
local clone = InputsFolder:Clone()
clone.Parent = player
end
Players.PlayerAdded:Connect(onPlayerAdded)
for _, player in Players:GetPlayers() do
onPlayerAdded(player)
end

En utilisant ce modèle, vous pouvez lire les InputActions pour tous les joueurs dans RunService:BindToSimulation() à la fois sur le client et le serveur pour recevoir les mêmes données pour une image donnée et enregistrer l'entrée de l'image précédente dans un attribut, par exemple pour déclencher une course de personnage lorsqu'une action d'entrée RunAction est déclenchée.

Événements distants

Les événements distants peuvent toujours être utilisés dans le modèle d'autorité du serveur pour faciliter la communication discrète entre le client et le serveur. Par exemple, les serveurs peuvent utiliser des événements distants pour diffuser des données sur les joueurs marquant des points ou ramassant des objets, et les clients peuvent utiliser des événements distants comme une API alternative pour envoyer des entrées au serveur, comme pour des pressions de boutons ou des tapotements d'objets dans le monde 3D.

Animations

Les animations qui affectent le gameplay, telles que le mouvement du personnage ou les animations d'attaque, doivent être contrôlées à l'intérieur de fonctions liées via BindToSimulation() dans le même ModuleScript qui s'exécute à la fois sur le client et le serveur. Les membres principaux de Animator et AnimationTrack tels que LoadAnimation(), Play(), Stop(), AdjustSpeed(), et TimePosition ont accès à la simulation.

L'état d'animation fait partie de la simulation prédite. Lorsqu'un retour en arrière se produit pendant une animation, le client rembobine l'animation à l'état autoritaire et la rejoue avec le reste de la simulation, de sorte que les animations du client et du serveur restent synchronisées. Comme le client peut remplacer les pistes d'animation lors d'un retour en arrière, ne mettez pas en cache les références AnimationTrack entre les images. Au lieu de cela, recherchez la piste en direct à chaque image avec Animator:GetTrackByAnimationId(). Pour un exemple complet, voir écriture de code d'animation.

Sons et effets

Les effets côté client comme les sons et les particules doivent être écrits en sachant que la simulation du client n'est qu'une prédiction de l'état autoritaire du serveur. BindToSimulation() limite ce que les propriétés et méthodes peuvent être appelées à partir de fonctions liées pour vous aider à écrire uniquement à l'état de simulation synchronisé. Afficher les résultats de cette simulation, déclencher des effets et des sons, etc. devrait se faire dans une fonction séparée connectée à RenderStepped qui lit les résultats de la simulation et déclenche les effets souhaités.

Parce que le client pourrait prédire un événement qui ne se produit jamais sur le serveur, votre code de rendu devrait être capable d'annuler ou de cacher les effets mal prédites. D'autres conseils sur le rendu d'une simulation prédite sont couverts dans lecture de sons et d'effets visuels.

Projets d'exemple

En plus de cette documentation, les modèles suivants peuvent vous aider à démarrer :

Course
Football
Laser Tag
©2026 Société Roblox. Roblox, le logo Roblox et Powering Imagination font partie de nos marques déposées aux États-Unis et dans d'autres pays.