J'ai lu Valve + Gafferon et des centaines de pages de Google, mais pour une raison quelconque, je ne comprends pas très bien comment prévoir les clients.
À ma connaissance, le problème fondamental est le suivant:
- Le client A envoie une entrée à
T0
- Le serveur reçoit les entrées à
T1
- Tous les clients reçoivent le changement à
T2
A T2
Cependant, en utilisant la prédiction du client, le client A est maintenant à une appropriée de position T4
.
Comment vous assurez-vous que le client A, lorsqu'il prédit que le serveur acceptera la demande de mouvement, ne sera pas en avance sur le serveur? Évidemment, tout le temps où ils sont en avance, il en résulte un retour à l'endroit où le serveur les a vu pour la dernière fois. Avec toutes les corrections que j'ai essayées, ceci est toujours visible lorsque vous vous arrêtez, car le serveur s'arrête derrière vous.
la source
Je n'ai pas encore implémenté ceci (donc il pourrait y avoir des problèmes que je ne vois pas immédiatement), mais je pensais que j'essaierais de vous aider.
Voici ce que vous avez dit se passe:
Il serait probablement utile de penser en termes de temps serveur. Son (probablement) très similaire à la façon dont fonctionne l' interpolation .
Chaque commande est envoyée avec une heure de serveur. Cette heure de serveur est calculée au début d'une correspondance en interrogeant le tick du serveur, en compensant la durée du ping. Sur le client, vous avez votre propre compte de ticks local et chaque commande que vous envoyez est convertie en ticks de serveur (c'est une simple opération de soustraction).
De plus, le client restitue toujours "dans le passé". Donc, vous supposez que le monde que le client voit est, disons, 100 ms en retard sur le temps réel du serveur.
Donc reformulons votre exemple avec l'heure du serveur (désignée par S).
Le client envoie une entrée à T0 avec l'heure du serveur S0 (ce qui, je suppose, est "la représentation du temps du serveur par le client moins le temps d'interpolation"). Le client n'attend pas la réponse du serveur et se déplace immédiatement.
Le serveur reçoit une entrée en T1. Le serveur détermine la position faisant autorité du client à l'heure du serveur SO donnée par le client. Envoie cela au client.
Le client reçoit la position faisant autorité en T2 (toujours avec la désignation de l’heure du serveur SO). Le client garde une trace de la durée passée des événements précédents (probablement juste une file d'attente de toutes les prédictions non confirmées).
Si la position / vitesse / tout ce que le serveur renvoie à S0 est différent de ce que le client a stocké à S0, le client s'en charge en quelque sorte. Soit en ramenant le joueur à sa position passée, soit en ré-imitant l'entrée précédente, soit peut-être quelque chose d'autre auquel je n'ai pas pensé.
la source
En fait, il y a une implémentation open-source dans github qui montre comment faire. Découvrez Lance.gg
github repo: https://github.com/lance-gg/lance
Le code de prédiction client est implémenté dans le module appelé
src/syncStrategies/ExtrapolateStrategy.js
Outre l'extrapolation, il y a deux concepts que je n'ai pas vus mentionnés ci-dessus:
la source
Le client A est toujours en avance sur le serveur - mais cela n'a pas d'importance. Vous devez seulement ramener le client en arrière si le serveur dit qu'il y a eu un problème avec la position signalée, à quel point le client réexécute tous les changements qu'il a apportés depuis l'erreur avec les valeurs corrigées, pour le rendre à un état compatible. avec le serveur.
Pour ce faire, le client doit se souvenir de certains états et mises à jour passés. Ce ne peut être que quelques valeurs simples telles que la position, la vitesse, l’orientation, ce genre de chose. Le serveur enverra périodiquement un accusé de réception indiquant que différentes mises à jour du client étaient légitimes, ce qui signifie qu'elles peuvent maintenant être oubliées du client. Toutefois, si le serveur signale qu'une mise à jour était invalide, l'état du client revient à ce point et les modifications futures sont appliquées à cet état modifié.
Il y a quelques liens supplémentaires au bas de l'article de Valve qui méritent d'être lus - c'est l'un d'entre eux: https://developer.valvesoftware.com/wiki/Prediction
la source
t=4
) reçoit des informations à propos det=2
, de sorte qu'il réinitialise l'état pour réexécutert=2
ensuite les mises à jour pour amener les objets det=2
àt=4
?