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.
-- 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)
-- Spawned on the client: only this player sees it
local marker = Particle(Vector(0, 0, 200), Rotator(), "nanos-world::P_Fire", false, true)
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 chose | Events.BroadcastRemote / Events.CallRemote |
| Prévenir le serveur que le joueur a fait quelque chose | Events.CallRemote (sur le client) |
| Garder sur une entité une valeur que tous les joueurs doivent connaître, maintenant et plus tard | entity:SetValue(key, value, true) |
| Garder une valeur globale que tous les joueurs doivent connaître | Server.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.
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
Timersuffit souvent, et le client peut interpoler le reste. - N'envoyez qu'à ceux qui en ont besoin :
Events.CallRemotepour un seul joueur,Events.CallRemotePlayerspour une liste de joueurs, ouEvents.BroadcastRemoteInRadiuspour 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.