J'implémente un clone d'astéroïdes multijoueur pour en savoir plus sur l'architecture réseau client / serveur dans les jeux. J'ai passé du temps à lire les publications de GafferOnGames et Valve sur leur technologie client / serveur. J'ai des problèmes avec deux concepts.
Actuellement, j'ai un serveur de jeu faisant autorité qui simule la physique avec box2d et envoie l'état du monde aux clients environ 20 fois par seconde. Chaque client garde une trace des derniers instantanés qu'il a reçus et lerps entre deux états pour lisser le mouvement des sprites. Mais ce n'est pas si simple. Il peut être lisse pendant un certain temps, puis saccadé un peu, puis revenir à lisse, etc. J'ai essayé à la fois TCP et UDP, les deux sont à peu près les mêmes. Une idée de mon problème? (Remarque: j'ai d'abord implémenté cela pour le mode solo, et le mouvement des sprites est parfaitement fluide à 60 images par seconde lors de la mise à jour du monde physique seulement 20 fois par seconde).
Afin de résoudre le premier problème, j'ai pensé que le client devrait peut-être également exécuter une simulation box2d et simplement mettre à jour les positions de ses sprites pour correspondre aux instantanés du serveur lorsqu'ils ne correspondent pas. Je pensais que cela pourrait être plus fluide car mon implémentation en mode solo est fluide. Est-ce une bonne idée?
Même si cela ne résout pas le problème ci-dessus, est-ce nécessaire pour la prédiction côté client? Par exemple, si un joueur tente de déplacer son vaisseau, comment saura-t-il s'il frappe un astéroïde, un mur ou un vaisseau ennemi sans simulation physique? Il semble que leur vaisseau semble traverser l'objet avec lequel il devrait entrer en collision avant de recevoir un instantané du serveur indiquant qu'ils ont heurté l'objet.
Merci!
la source
+-*/
» est complètement fausse. Toutes ces opérations dans IEEE-754 peuvent varier en fonction de la mise en œuvre. Voir ici et ici pour plus d'informations.Cela ne semble probablement pas si bon, car l'interpolation entre eux repose sur le fait d'avoir toujours le prochain ensemble de données à interpoler. Cela signifie que, s'il y a une courte pointe de décalage, tout doit attendre pour rattraper le retard.
Il y a un ancien article sur GameDev sur l'utilisation de splines cubiques pour prédire la position d'un objet au-delà du point où vous aviez pour la dernière fois des données. Vous utilisez ensuite cette position, puis ajustez la spline lorsque vous obtenez de nouvelles données pour tenir compte de sa nouvelle position. C'est aussi probablement beaucoup moins cher que d'exécuter une deuxième simulation physique, et cela signifie que vous n'avez pas à décider à qui vous faites confiance, car vous avez explicitement implémenté le client en le constituant au fur et à mesure. :)
la source
J'ai fait des trucs similaires moi-même, et j'ai exécuté Box2D uniquement sur les clients. La façon dont je l'ai fait était de laisser le client exécuter sa propre simulation à peu près de lui-même, en envoyant la vitesse actuelle (et la rotation) sur chaque paquet de synchronisation au serveur. Le serveur envoie ensuite ces informations à d'autres joueurs, qui définissent les vitesses nouvellement reçues aux entités répliquées. C'était très fluide, sans aucune différence notable entre les clients.
Bien sûr, le problème ici est qu'il n'y a pas de contrôle centralisé sur les entités, mais je pense que cela pourrait également être fait côté serveur en faisant une simulation côté physique de la physique
la source
Je préférerais personnellement exécuter les simulations uniquement sur le serveur et lui faire diffuser les changements sur les vitesses / accélérations linéaires / angulaires des objets impliqués chaque fois qu'ils se produisent. C'est, quand un certain objet, pour une raison quelconque, change l'une de ses propriétés physiques (telles que les vitesses et accélérations susmentionnées), cette modification spécifique sera envoyée du serveur au client, et le client changera son côté de la les données de l'objet en conséquence.
L'avantage de celui-ci sur votre implémentation actuelle est qu'il annulera la nécessité d'interpolations côté client et générera un comportement très fidèle sur les objets. Le problème est que cette méthode est assez vulnérable aux latences, qui deviennent un très gros problème lorsque les joueurs sont géographiquement trop éloignés les uns des autres.
Quant à la question 1, je dis que le problème serait les fluctuations de la latence, car il n'y a aucune garantie absolue qu'il y aura un intervalle de 20 secondes exactement parfait entre chaque réception de l'instantané. Permettez-moi d'illustrer (étant "t" le temps mesuré en millisecondes):
1) À t = 20 depuis le début du jeu, le client a reçu un instantané et a effectué l'interpolation avec succès et en douceur.
2) À t = 40, il y avait une latence entre le serveur et le client, et l'instantané n'arrivait réellement qu'à t = 41.
3) À t = 60, le serveur a envoyé un autre instantané, mais une seconde de la simulation a été gaspillée côté client en raison de la latence. Si l'instantané arrive à t = 60, le client ne fera pas une interpolation des 40 et 60 instants, mais en fait des instants 41 à 60, générant un comportement différent. Cette inexactitude pourrait être à l'origine de la "secousse" éventuelle.
En ce qui concerne la question 2, votre idée pourrait fonctionner si vous implémentez quelque chose qui suivra efficacement si chaque objet est vraiment synchronisé client-serveur sans avoir à envoyer des packages à chaque trame en informant la position des objets. Même si vous le faites à des intervalles discrets, vous exécuterez non seulement le même problème de la question 1, mais vous aurez également de trop grandes quantités de données à transférer (ce qui est une mauvaise chose).
la source