Entrée côté serveur


9

Actuellement dans mon jeu, le client n'est qu'un rendu. Lorsque l'état d'entrée est modifié, le client envoie un paquet au serveur et déplace le lecteur comme s'il traitait l'entrée, mais le serveur a le dernier mot sur la position.

Cela fonctionne généralement très bien, sauf pour un gros problème: la chute des bords. Fondamentalement, si un joueur marche vers un bord, disons une falaise, et s'arrête juste avant de sortir du bord, parfois une seconde plus tard, il sera téléporté hors du bord. Cela est dû au fait que le paquet «J'ai arrêté d'appuyer sur W» est envoyé une fois que le serveur a traité les informations.

Voici un diagramme de décalage pour vous aider à comprendre ce que je veux dire: http://i.imgur.com/Prr8K.png

Je pourrais simplement envoyer un paquet "W pressé" à chaque trame pour que le serveur le traite, mais cela semblerait être une solution coûteuse en bande passante.

Toute aide est appréciée!

Réponses:


5

Bien que le serveur ait le dernier mot sur la position, il doit le faire en vérifiant et en vérifiant la raison de ce que le client envoie comme entrées et position. Je dis cela parce que ce que vous faites déplace immédiatement le joueur et l'attente qui crée dans votre code est que le client est la vraie position.

Vous pensez que cela fonctionne généralement bien, mais ce n'est pas le cas. Remarque: vous dites que votre client n'est rien de plus qu'un moteur de rendu, puis lui donnez rapidement le contrôle local pour se déplacer sans messages du serveur. Vous ne pouvez pas jouer sur les deux tableaux, soit attendre que le serveur vous dise de bouger, soit assumer un certain contrôle sur votre position et utiliser le serveur pour vérifier les tricheurs.

Je note que vos réponses atteignent une seconde entière? C'est une latence de 500 ms, ce qui est ridiculement grand pour tout type de jeu d'action. Essayez de comprendre pourquoi ce retournement prend autant de temps, il peut s'agir de files d'attente de commandes sauvegardées de ne pas être traitées rapidement à une bande passante inondée ou même des démons provoquant de nombreux paquets perdus.

Je pense que ce qui devrait arriver est que

client sends a move + position update
server gets it t+latency time later
server verifies and sends out info to all clients
client receives this at (t+latency + latency)

La partie délicate ici est que si un client reçoit un message sur lui-même, il doit surtout l'ignorer à moins que ce message ne soit quelque chose comme "un mouvement invalide, allez plutôt à XYZ". Si ce message s'adresse au client de quelqu'un d'autre sur lequel vous obtenez des informations, vous devrez extrapoler en avant dans le temps afin qu'il semble être un peu là où il se trouvera.


Le client n'envoie pas du tout sa position; il prédit / interpole simplement. C'est pourquoi il tombe sur les bords lorsqu'il pense qu'il est sur le bord. De plus, je ne vois pas où j'ai dit que le décalage était de 1 seconde, cela ressemble plus à 8 ms (test local) à 100 ms (sur Internet). J'ai dit que le joueur reculerait plus tard parce que j'envoie périodiquement des mises à jour complètes de position. Ai-je raison de comprendre que je devrais envoyer la position que le client pense qu'elle devrait être, avec les touches qui ont été pressées, et le serveur devrait vérifier si c'est possible?
Thomas

"Parfois, une seconde plus tard, il sera téléporté", impliquait les gros retards, d'où mon temps. Pour un jeu d'action réactif oui, le client joue et le serveur joue en retard et fait savoir au client s'il a fait quelque chose d'illégal. Vous remarquerez que dans les jeux multijoueurs en ligne, vous voyez principalement les autres personnes changer de position (celles provenant du serveur) tandis que votre propre position ne change que très rarement par rapport aux corrections directes du serveur. D'autres personnes vous voient changer de position, etc ...
Patrick Hughes

Cela ne pourrait-il pas encore faire tomber le joueur du bord du serveur? À moins que j'envoie un paquet à chaque trame, le serveur pourrait toujours penser que le lecteur se déplace pendant environ 32 ms. (J'envoie seulement des paquets toutes les trois trames). Ou suggérez-vous que je ne simule pas du tout l'entrée sur le serveur, mais que je vérifie plutôt si la position est dans les limites de l'entrée appuyée?
Thomas

Étant donné que le serveur ne corrige que les mouvements non valides signalés par le client, il n'enverra jamais de message "vous êtes tombé de la falaise" à moins que le client lui-même ne soit allé directement sur le bord. Dans cette boucle de rétroaction, c'est le serveur qui se corrige selon la vision du monde du client et sa place dans celui-ci. Le mouvement sera net et réactif au joueur. D'autres actions telles que l'interaction avec des objets mondiaux impliqueront d'attendre que le serveur dise au client ce qui vient de se produire, de cliquer sur une case et d'attendre une réponse, mais nous parlons simplement de mouvement ici.
Patrick Hughes

Cela ressemble beaucoup à ce que je fais actuellement; envoyer une position au serveur et faire valider par le serveur si le joueur aurait pu se déplacer vers cette position. Cela semble être une approche plus heuristique et, à mon avis, ne serait pas aussi efficace que de décider du serveur, point final. L'envoi d'horodatages avec chaque paquet fonctionnerait-il? Je pense que cela éliminerait le problème. Je crois que Halo et les jeux qui utilisent le moteur Source l'utilisent.
Thomas

0

Je comprends que votre question soit:

Le serveur reçoit un paquet lorsque je commence à appuyer sur le bouton «Suivant» et un autre paquet lorsque je relâche enfin le bouton «Suivant». Par conséquent, le mouvement réel sur le serveur commence et se termine environ 100 millisecondes «trop tard» dans le jeu réel par rapport à ce que le joueur exprime côté client. Donc, si le joueur veut se déplacer de 10 secondes, il peut finir par se déplacer 10.x secondes à la place x >= 1.

Il s'agit d'une mauvaise stratégie de conception car elle n'exprime pas la volonté du joueur dans le monde du jeu comme le souhaite le joueur, créant une expérience utilisateur plutôt médiocre.

La solution que je recommanderais est d'envoyer un paquet (aussi souvent que possible) qui indique combien de pas le joueur a pris et dans quelle direction. Le serveur met ensuite à jour le monde du jeu avec le nouvel emplacement du joueur s'il réussit un contrôle d'exactitude. Ainsi, le joueur peut se déplacer avec une grande précision et éviter de tomber de hauts rebords.

L'alternative serait de se souvenir des positions du joueur dans la dernière seconde et de corriger la position rétrospectivement au moment où le bouton a été relâché. On dirait que cela créerait cet effet élastique des temps anciens (uniquement pour une raison différente)

Donc, fondamentalement, vous devrez envoyer un paquet de quel bouton est pressé et quelle était l'heure de jeu réelle sur laquelle le bouton a été pressé, puis plus tard, quel bouton a été relâché et à quelle heure exacte.


Comme je l'ai dit à Patrick, je pense que cette solution serait davantage une approche heuristique; au lieu que le serveur soit "The Man", le serveur vérifie la validité des données client. Bien sûr, cela devra créer une certaine marge de manœuvre pour que le décalage ou d'autres problèmes de réseau ne créent pas de faux positifs.
Thomas
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.