Comment synchroniser plus efficacement l'état d'un jeu multijoueur que les mises à jour complètes?


10

J'ai déjà fait un peu de codage de réseau de jeux, mais principalement avec TCP pour des jeux sans besoins en temps réel. Je travaille sur un jeu Java 2D avec multijoueur en réseau. Pour apprendre, je veux le faire moi-même, sans API réseau existante.

Comment représenter efficacement l'état du jeu envoyé aux clients à partir d'un serveur? Il existe le moyen le plus évident mais probablement le moins efficace, qui serait de créer une sorte d'objet contextuel d'état du jeu avec l'emplacement de chaque joueur, l'état d'animation, etc., et de l'envoyer à chaque joueur à chaque mise à jour . Cela ne semble pas très difficile à mettre en œuvre, mais serait probablement trop important pour réaliser quelque chose de proche de l'interaction en temps réel (bien sûr, mon expérience avec cela est limitée, donc je peux être incorrect).

Y a-t-il un moyen solide que vous avez utilisé auparavant pour ne transmettre que les changements d'état, et y a-t-il même une disparité de performances suffisamment importante pour que cela en vaille la peine?


2
Essayez l'état complet de chaque image et si c'est trop lent (pour un jeu 2d quelque peu simple, c'est probablement assez efficace), essayez d'optimiser. Si cela fonctionne bien, cela fonctionne bien et vous n'avez pas à le changer, sauf si vous remarquez que votre réseau est un goulot d'étranglement plus tard.
Robert Rouhani

Réponses:


10

La transmission régulière de l'état complet du jeu n'est généralement pas possible, bien que cela dépende beaucoup de la complexité de votre jeu. Pour un jeu simple avec un petit modèle mondial, cela peut fonctionner.

J'ai personnellement eu beaucoup plus de succès avec le modèle suivant:

  • État du jeu stocké dans un modèle d'objet bien défini dans une structure de données spatiales (par exemple un octree)
  • Toutes les modifications de l'état du jeu (que ce soit sur le client ou sur le serveur) sont décrites comme des événements. Un événement peut être un changement de propriété sur un objet de jeu, un changement sur une tuile de carte, le mouvement d'un objet de jeu, etc.
  • Le moteur de jeu sur le serveur produit un flux d'événements au cours du jeu. Ceux-ci sont directement appliqués à l'état de jeu du serveur.
  • Les événements sont également envoyés aux joueurs, mais uniquement si l'événement est pertinent pour ce joueur (par exemple, l'événement est-il visible depuis la position actuelle?)
  • Les changements dans la visibilité des joueurs peuvent également entraîner des événements pour "révéler" de nouvelles parties de la carte, etc. lorsque le joueur se déplace. Cela peut également être utilisé pour s'assurer que le joueur obtient une vue initiale précise de l'état du jeu pertinent lors de sa première participation au jeu.
  • L'état du jeu pour le joueur est mis à jour avec tous les événements qu'il reçoit. En tant que tel, il n'a qu'un modèle partiel de l'état du jeu, mais il doit rester synchronisé avec le serveur en supposant que tous les événements sont correctement traités

Cela m'a donné de bonnes performances avec des mondes de jeu même assez grands.

Autre astuce, laissez le client s'occuper de l'animation, des effets de particules, etc. sans référence au serveur. Cela ne sert à rien de les transmettre - ils doivent simplement être "déclenchés" par les événements de jeu appropriés.


6

La synchronisation est généralement divisée en deux parties: incrémentale et absolue.

Parfois, vous devez tout transmettre, c'est grand, mais si vous l'emballez correctement, vous pouvez le faire une fois toutes les quelques secondes. Il est bon de mettre tout en place, en corrigeant les défauts des rafraîchissements incrémentiels.

Pour obtenir une expérience en temps réel, vous devez transmettre rapidement certains changements, mais uniquement les attributs qui peuvent changer. Par exemple, si une fusée vole en ligne droite, vous n'avez pas besoin de mettre à jour la position, chaque client peut la calculer à partir du point de départ. Mais quand il frappe, vous pouvez générer un message à ce sujet, afin que chaque client puisse exploser la fusée au bon endroit. Les problèmes mineurs peuvent être ignorés.

Bien sûr, vous ne mettez à jour les choses que lorsqu'elles peuvent influencer le client! Quelque chose loin de l'écran n'en vaut pas la peine. Certaines valeurs peuvent être mises à jour moins fréquemment. Par exemple, les positions sont importantes pour être plus ou moins précises, les événements (mort, coup de feu, explosion, etc.) doivent être envoyés instantanément, tandis que les valeurs non directement importantes peuvent avoir des périodes de rafraîchissement inférieures, par exemple tableau de bord, chat.

L'emballage des données est également important. Vous pouvez transmettre environ 1400 octets (en fonction de la configuration, c'est la valeur par défaut) dans un package UDP, généralement il y a quelques octets d'en-tête. Ainsi, vous pouvez facilement mettre à jour 50 à 100 positions d'unité dans un seul package.


Merci pour les conseils Matzi. Je travaille toujours sur la mise en œuvre du serveur et du client, mais je reviendrai dans quelques jours et j'accepterai probablement votre réponse.
Haz

Bonne chance à toi! ;)
Matzi

1

En fonction de votre jeu, vous pouvez envisager un modèle d '"exécution synchronisée" où chaque client arrive à jouer le même jeu en partageant simplement des entrées non déterministes comme les entrées clavier / joystick et les événements de la minuterie. (Par rapport à un modèle où chaque client exécute des simulations locales et s'attend à intégrer les résultats des simulations à distance). Votre moteur de jeu doit généralement être entièrement déterministe pour que cela fonctionne, ce qui peut être un lourd fardeau selon le jeu. Mais si le jeu est déjà déterministe, cela peut être une approche plus facile.

Ce message #AltDevBlogADay couvre certains aspects de cette approche dans un RTS moderne (en particulier comment détecter quand vos clients commencent à exécuter des jeux "différents".)

N'oubliez pas de rester simple jusqu'à preuve du contraire. :)


1
Ce sont de bonnes lectures du développeur de Factorio qui utilise cette approche, et font allusion à la complexité de cette approche, mais montrent également qu'elle est viable: factorio.com/blog/post/fff-76 factorio.com/blog/post/fff -147 factorio.com/blog/post/fff-188
AaronLS
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.