Synchronisation des clients avec un serveur et entre eux

9

Quelle est la meilleure façon de garder tous les clients synchronisés avec un serveur et entre eux?

Actuellement, nous avons deux approches en tête:

  1. Lorsqu'un client envoie quelque chose au serveur, le serveur envoie immédiatement des messages à tous les clients, qui réagissent immédiatement.
  2. Introduire un certain délai, par lequel le serveur envoie des messages à tous les clients, avec la directive, "agissez en conséquence t.

La deuxième approche semble comme elle aurait plus de chances de maintenir tous les clients dans une meilleure synchronisation (car elle répond à un certain degré de retard); mais je me demande si la réactivité serait perdue à un degré trop élevé (c'est-à-dire que l'utilisateur clique sur «sauter» et qu'il y a un écart notable entre appuyer sur le bouton et sauter réellement).

Il y a aussi la possibilité pour les clients de calculer leur propre position (et de ne pas attendre que les serveurs disent "vous avez sauté"); mais en raison du décalage inévitable, les clients seraient très désynchronisés.

Ensuite, il y a toute la question TCP vs UDP; parce que nous le voulons rapidement, mais je détesterais aussi que le serveur dise que vous êtes dans un endroit complètement différent de ce que vous pensiez être.

Avec toutes ces demandes concurrentes, il devient très incertain comment nous devons aborder cette question. Laquelle de ces approches (ou toute autre) serait la meilleure pour garder les clients et le serveur tous synchronisés? Lesquels sont réellement utilisés dans l'industrie?

Smashery
la source

Réponses:

7

La réponse rapide est: il n'y a pas de meilleure approche.

Les jeux contiennent tous une architecture différente; chaque jeu choisira différents ensembles de données à envoyer afin de se synchroniser avec les autres machines, ce qui affectera les choix que vous pouvez faire lorsque vous choisissez comment gérer le décalage.

Ce que vous spécifiez dans l'option # 2 - que les clients envoient des messages pour être traités ultérieurement - est certainement une approche. En fait, le moteur source utilise une variante de cette approche , où le rendu est toujours à 100 ms derrière les actions du client local; toutes les machines tentent d'opérer sur les mêmes actions en même temps. Cela ajoute un décalage artificiel et imperceptible au jeu afin de masquer la latence réelle du réseau.

Si vous ne pouvez pas adopter cette approche, vous pouvez également choisir l'option # 1, en envoyant simplement les données les plus à jour et à la réception, utilisez l'interpolation et l'extrapolation (prédiction côté client) pour essayer de masquer la latence. J'ai utilisé cette approche dans au moins un jeu d'expédition - mais encore une fois, tout dépend de votre jeu; il peut y avoir d'autres approches que vous pouvez adopter.

Enfin, lorsque vous choisissez entre TCP et UDP - vous voulez probablement UDP. Il existe des scénarios où TCP est une option viable pour mettre en réseau votre jeu, mais lorsque vous créez un jeu d'action, vous voulez les dernières données le plus tôt possible. Si vous pouvez gérer vous-même les paquets perdus, UDP est le meilleur choix. (Il existe des bibliothèques, telles que ENet , qui fournissent une enveloppe autour d'UDP pour remplacer les fonctionnalités de TCP, telles que les paquets fiables.)

Blair Holloway
la source
Vous ne voulez vraiment pas utiliser UDP. Les frais généraux d'une connexion TCP correctement configurée sont minimes et l'enfer qui est la livraison hors service est quelque chose que personne ne devrait avoir à vivre.
coderanger
2
Ce n'est pas une question de surcharge, bien que TCP en ajoute - la façon dont TCP traite les paquets perdus n'est fondamentalement pas bonne dans les jeux où une grande latence entre action et réaction peut faire une énorme différence dans la jouabilité. Pour un jeu comme WoW, où les actions sont relativement peu fréquentes, TCP fonctionne, mais il tomberait à plat dans un jeu comme CounterStrike, car un seul paquet abandonné étranglera votre connexion et vous fera potentiellement "attendre" pendant une seconde ou plus.
Blair Holloway
Si vous allez utiliser UDP, il est préférable de ne pas l'écrire vous-même; utilisez un wrapper comme ENet qui fait le travail dur pour vous. Mais ma réponse originale est toujours valable - UDP est la meilleure voie à suivre si vous créez un jeu avec une sorte d'action rapide.
Blair Holloway
Pour moi, RakNet a rendu l'exécution d'une connexion UDP pour mon moteur de jeu extrêmement facile. Il a de nombreuses options sur la façon dont vous souhaitez envoyer votre paquet, c'est-à-dire. comment les commander, si le paquet est renvoyé en cas de chute, etc.
BarakatX2
3

Voici quelques bons liens qui couvrent énormément de réseaux de jeux.

Et ceci est la première partie de la série de réseautage plus pratique. http://gafferongames.com/networking-for-game-programmers/udp-vs-tcp/

Pour l'histoire. «nous sommes désolés, mais en tant que mécanisme de prévention du spam, les nouveaux utilisateurs ne peuvent publier qu'un maximum d'un hyperlien. Gagnez 10 points de réputation pour publier plus d'hyperliens. Il suffit de regarder son site Web, de toute façon.

jsimmons
la source
1

Puisque vous mentionnez les clients et les serveurs, je vais supposer que vous parlez d'une architecture client / serveur où le serveur est l'autorité sur l'état de tous les objets.

Remarque: L'alternative est une architecture d'égal à égal où le propriétaire d'un objet est l'autorité pour cet objet.

Il existe déjà une méthode éprouvée pour synchroniser les objets en mouvement à l'aide d'une architecture client-serveur. C'est appelé Dead Reckoning. .

Un bon moyen de l'implémenter dans un jeu serait comme ceci:

  1. Les clients envoient des entrées au serveur.
  2. Le serveur met à jour les objets du jeu (accélérations et directions) et les renvoie aux clients.
  3. Les clients utilisent ces valeurs mises à jour pour simuler le mouvement des objets localement.
  4. Parfois, le serveur envoie une correction de position pour éviter la dérive.
  5. Rincer; répéter.
JanSolo
la source