Passer au contenu principal
Version: bleeding-edge 🩸

Réseau et réplication

Ce qui est synchronisé automatiquement entre le serveur et les clients, et comment envoyer vos propres données efficacement.

nanos world est server authoritative : le serveur détient le « vrai » état du jeu, et les clients le reçoivent et l'affichent. La plupart de la synchronisation est faite pour vous. Cette page explique comment elle fonctionne, pour que vous sachiez quand envoyer des données vous-même, et comment le faire sans gaspiller de bande passante.

Ce qui est synchronisé automatiquement​

  • Les entités créées sur le serveur sont automatiquement créées sur tous les clients, y compris pour les joueurs qui arrivent plus tard.
  • Les méthodes appelées sur le serveur (par ex. SetLocation, SetMaterialColorParameter, PlayAnimation) s'appliquent aussi automatiquement sur tous les clients.
  • Le mouvement des Characters, des véhicules et des Props physiques est synchronisé en continu (voir Network Authority plus bas).
  • Les valeurs synchronisées définies avec SetValue(key, value, true) sur le serveur sont envoyées à tous les clients, voir Valeurs d'entité.

Ce qui n'est pas synchronisé :

  • Les entités créées sur le client n'existent que pour ce client. C'est ainsi qu'on crée des éléments purement visuels, comme l'interface, les sons locaux et les particules.
  • Les méthodes appelées sur le client ne modifient que la copie de l'entité chez ce client (et le serveur peut l'écraser plus tard).
  • Les variables Lua ne sont jamais synchronisées : chaque côté (et chaque Package) a les siennes.
Server/Index.lua
-- Spawned on the server: every player sees it, including the ones who join later
local door = StaticMesh(Vector(0, 0, 100), Rotator(), "nanos-world::SM_Cube")

-- Called on the server: every player sees the change
door:SetMaterialColorParameter("Tint", Color.RED)
Client/Index.lua
-- Spawned on the client: only this player sees it
local marker = Particle(Vector(0, 0, 200), Rotator(), "nanos-world::P_Fire", false, true)
tip

Regardez les icônes d'autorité de chaque méthode dans la Scripting Reference : elles indiquent de quel côté la méthode peut être appelée et si elle sera synchronisée.

Envoyer vos propres données​

Pour envoyer une information qui ne fait pas partie de l'état d'une entité (par ex. « la manche a commencé », « ouvre le menu de la boutique », « le joueur a cliqué sur un bouton »), utilisez les Remote Events. Pour une information qui fait partie de l'état d'une entité ou du jeu (par ex. l'équipe d'un joueur ou le score), préférez les valeurs synchronisées, envoyées automatiquement aux joueurs qui arrivent plus tard.

Je dois...Utiliser
Prévenir les clients qu'il s'est passé quelque choseEvents.BroadcastRemote / Events.CallRemote
Prévenir le serveur que le joueur a fait quelque choseEvents.CallRemote (sur le client)
Garder sur une entité une valeur que tous les joueurs doivent connaître, maintenant et plus tardentity:SetValue(key, value, true)
Garder une valeur globale que tous les joueurs doivent connaîtreServer.SetValue(key, value, true)
Communiquer avec une entité précise de l'autre côtéentity:CallRemoteEvent / entity:BroadcastRemoteEvent

Reliable ou Unreliable​

Chaque événement distant est envoyé avec une Reliability :

  • Reliability.Reliable : arrivée garantie, et dans l'ordre. Les paquets perdus sont renvoyés jusqu'à leur arrivée. À utiliser pour tout ce qui est important : changements d'état du jeu, achats, chat.
  • Reliability.Unreliable : peut se perdre ou arriver dans le désordre, mais coûte moins cher et ne retarde jamais les autres messages. À utiliser pour les données envoyées très souvent quand seule la dernière compte : positions envoyées à chaque Tick, effets visuels, sons.
attention

Envoyer beaucoup d'événements Reliable (par ex. à chaque Tick) peut saturer la connexion des joueurs qui ont un mauvais réseau et retarder tout le reste. Si c'est envoyé à chaque frame, ça devrait presque toujours être Unreliable.

Envoyer moins​

La bande passante est limitée par joueur (voir max_send_rate dans la configuration du serveur). Quelques conseils pour la garder basse :

  • N'envoyez pas à chaque Tick sauf si c'est vraiment nécessaire. Envoyer 10 fois par seconde avec un Timer suffit souvent, et le client peut interpoler le reste.
  • N'envoyez qu'à ceux qui en ont besoin : Events.CallRemote pour un seul joueur, Events.CallRemotePlayers pour une liste de joueurs, ou Events.BroadcastRemoteInRadius pour les joueurs proches, au lieu de diffuser à tout le monde.
  • Envoyez des identifiants, pas des tables entières : si les deux côtés connaissent déjà les données (par ex. une liste d'objets définie dans Shared/), envoyez juste l'identifiant de l'objet.
  • Passez directement les entités : elles peuvent être passées en paramètre des événements distants et arrivent comme la même entité de l'autre côté, inutile d'envoyer vous-même leur position ou leur identifiant.
  • Évitez les valeurs synchronisées qui changent très souvent : chaque changement est envoyé à tous les joueurs.

Autorité Réseau​

La physique (et l'IA) n'est pas simulée par le serveur. Le serveur choisit plutôt un client comme Network Authority de chaque entité physique (en général le joueur le plus proche, ou celui qui interagit avec elle) : ce client la simule et envoie son mouvement au serveur, qui le transmet à tous les autres.

C'est pour ça que certaines méthodes et certains événements sont marqués comme disponibles côté Network Authority. Plus de détails dans Network Authority.

Distance Optimization​

Pour économiser de la bande passante, le serveur envoie moins souvent à chaque joueur les mises à jour de mouvement des entités éloignées. Cela ne concerne que les données unreliable (mouvements et actions passagères) : les données reliable, comme les créations, destructions, événements distants et changements de valeur, sont toujours livrées.

Vous pouvez l'ajuster par entité ou par joueur avec SetDistanceOptimizationMultiplier, voir Optimisation par distance.

Dimensions​

Les entités et les joueurs peuvent être séparés dans différentes dimensions : les joueurs ne reçoivent que les entités de leur dimension. C'est utile pour les lobbies, les intérieurs instanciés ou plusieurs parties sur le même serveur.