Quoi envoyer au serveur en temps réel dans un jeu FPS?

23

Quelle est la bonne façon de dire la position de notre acteur local au serveur? Certains documents disent qu'il vaut mieux envoyer les intrants chaque fois qu'ils sont produits. Et certains documents disent que le client envoie sa position dans un intervalle fixe.

Avec l'approche d'envoi des entrées: que dois-je faire si le joueur maintient les touches de direction enfoncées? Cela signifie que je dois envoyer un paquet au serveur dans chaque trame. N'est-ce pas trop? Et il y a aussi la rotation du joueur à partir de l'entrée de la souris. Voici un exemple:

http://www.gabrielgambetta.com/fpm_live.html

Qu'en est-il de l'envoi de la position en approche à intervalle fixe. Il envoie trop peu de messages au serveur. Mais cela réduit également la réactivité.

Alors quelle voie est la meilleure?

syloc
la source

Réponses:

19

Réponse simple: trichez ou ne soyez pas aussi précis!

Si vous avez joué à un jeu de tir en ligne, vous aurez très probablement connu le soi-disant «élastique» si votre connexion au serveur est mauvaise.

Cela est dû au fait que votre client corrige votre position de temps en temps.

Fondamentalement, ce qui se passe des deux côtés:

  • Le serveur suivra votre mouvement et enverra les mises à jour aux clients comme prévu. Il ne s'agit pas toujours de mises à jour complètes. Toutes les x images, il pourrait y avoir une mise à jour complète, toutes les autres images que vous envoyez uniquement de nouveaux vecteurs de vitesse (s'il y a des changements).

  • Votre propre client vous permettra de vous déplacer librement mais utilisera les mises à jour fournies par le serveur pour corriger / ajuster votre position. Cela garantira que le jeu se sent réactif, même si vous ne mettez pas à jour la position image par image.

Mais comment les entrées sont-elles gérées? Votre client enverra votre position au serveur "J'ai déménagé là-bas". Le serveur vérifiera cette mise à jour (par exemple, devriez-vous être en mesure de vous y déplacer aussi rapidement?) Et si elle est valide, déplacez-vous (ou rejetez votre mise à jour, ce qui se traduit par des «élastiques»).

Alors oui, votre approche à intervalle fixe fonctionnera très probablement et sera suffisante.

Mais même si vous voulez envoyer une entrée et gérer le mouvement des deux côtés, gardez à l'esprit que vous n'avez pas à envoyer "le bouton est toujours enfoncé". Envoyez plutôt un événement lorsque vous appuyez sur le bouton et un autre une fois le bouton relâché.

Mario
la source
5
Oui, je peux suivre la pression et le relâchement du bouton. Mais qu'en est-il de la saisie de la souris? Elle est en constante évolution.
syloc
6
"Au lieu de cela, envoyez un événement lorsque le bouton est enfoncé et un autre une fois le bouton relâché." - C'est vrai, mais il doit y avoir des vérifications en place pour s'assurer que l'événement "à la sortie" est finalement forcé, selon les règles des jeux. Par exemple, dans le multijoueur Rainbow Six Vegas 2 , un joueur peut commencer à tirer avec son arme, et un bug (malheureusement courant) empêche le message "stopper le tir" d'atteindre le serveur avec succès. Il en résulte que le son du coup de feu reste dans une boucle infinie pour le reste du match. Un seul exemple dont il faut se méfier. youtu.be/GOQIbLCy7m8?t=9m10s
Mike Baxter
@syloc: Manipulez-le simplement côté client et laissez le serveur déterminer si le mouvement est valide / possible (pour éviter des trucs tels que des hacks de téléportation et similaires).
Mario
@syloc Définissez simplement un intervalle pour la souris, mais pour économiser de la bande passante supplémentaire, effectuez toujours une vérification côté client pour voir si elle a changé. S'il y a une période sans mouvement de la souris, vous n'avez pas besoin de continuer à envoyer des messages à ce sujet.
agweber
Dans l'un de mes emplois, un ingénieur s'est pratiquement rendu fou en optimisant le comportement du ressort pour les mises à jour de position manquées pour l'accès à distance (il y a 13 ans). Maintenant, je vois des jeux avec beaucoup de bande passante et une latence ridiculement faible souffrant de ce problème, il semble que le problème ne disparaîtra jamais ou que les gens s'en soucient beaucoup moins de nos jours.
Andon M. Coleman
5

Si vous ne l'avez pas déjà fait, je vous suggère de lire ces deux articles approfondis mais compréhensibles: https://developer.valvesoftware.com/wiki/Source_Multiplayer_Networking et http://fabiensanglard.net/quake3/network.php .

Ceux-ci expliquent pourquoi il est conseillé d'utiliser l'envoi de paquets à «intervalle fixe». Pour être bref, c'est en fait surtout important pour les paquets envoyés par le serveur.

L'envoi d'un paquet a un coût fixe et la taille maximale d'un paquet réseau est d'environ 1,5 Ko. Donc, si vous avez par exemple 16 joueurs sur votre serveur, chaque image lorsque vous calculez le mouvement pour un joueur, un code naïf pourrait envoyer un paquet de mise à jour à chaque joueur après chaque résolution de mouvement, donc 16 * 16 = 256 paquets. Si vous avez une fréquence d'images de 30, cela représente 7680 paquets.

Une meilleure approche consiste à créer un tampon à chaque début de trame, à y concaténer la mise à jour de vos 16 positions calculées, puis à les envoyer à vos 16 joueurs.

Vous n'envoyez maintenant que 480 paquets par seconde pour les mêmes résultats.

Dans le cas du joueur au serveur, cela signifie simplement que vous devez envoyer, dans le même paquet, un maximum de données, comme; regardé la position, les actions appelées ce cadre et ainsi de suite.

À propos de la deuxième partie de votre question - la façon dont j'ai choisi de réduire la sensation de décalage était d'envoyer ces informations au serveur sur chaque trame:

  • position actuelle réelle du joueur (utilisée par le serveur pour vérifier si les positions côté serveur et côté joueur ne sont pas trop désynchronisées).

  • Position estimée du joueur en 1 seconde: calculée par le client: si le joueur ne change pas la direction de la souris et laisse le clavier dans son état actuel pendant 1 seconde, où sera le joueur? (nous ne nous soucions pas des collisions) Si le joueur ne bouge pas, sa position estimée en 1 seconde est sa position actuelle.

  • La position qu'il regarde.

Chaque fois que le serveur reçoit ces informations, il met à jour la position future et la position regardée, et l'entité joueur se déplace finalement vers sa position future.

Les joueurs ne sont jamais exactement synchronisés, mais la réponse d'entrée est instantanée (le plus important pour moi) et j'ai trouvé que les positions prédites étaient suffisamment précises pour moi.

GaelFG
la source
"Les joueurs ne sont jamais exactement synchronisés" Je pense qu'il est également important de mentionner que le niveau de précision ici dépend du jeu réel (jeu). Par exemple, un MMO classique où il suffit de cliquer et de sélectionner des entités, n'aura pas besoin d'une précision parfaite pour à peu près tout, mais dans un jeu de tir, une synchronisation parfaite à parfaite est essentielle.
Mario
La chose est, personne dans leur bon sens n'utilise TCP pour un FPS. Ils préfèrent gérer un reséquençage compliqué et des datagrammes manqués que d'engager la surcharge de TCP.
Andon M. Coleman