Je travaille sur un jeu de tir 2D descendant et je fais de mon mieux pour copier les concepts utilisés dans les jeux en réseau comme Quake 3.
- J'ai un serveur faisant autorité.
- Le serveur envoie des instantanés aux clients.
- Les instantanés contiennent un horodatage et des positions d'entité.
- Les entités sont interpolées entre les positions des instantanés afin que le mouvement soit fluide.
- Par nécessité, l'interpolation d'entité se produit légèrement "dans le passé" de sorte que nous avons plusieurs instantanés dans lesquels interpoler entre.
Le problème auquel je suis confronté est la "synchronisation d'horloge".
- Par souci de simplicité, supposons un instant qu'il n'y a aucune latence lors du transfert de paquets vers et depuis le serveur.
- Si l'horloge du serveur a 60 secondes d'avance sur l'horloge du client, un horodatage d'instantané aura 60000 ms d'avance sur l'horodatage local du client.
- Par conséquent, les instantanés d'entité seront collectés et assis pendant environ 60 secondes avant que le client ne voit une entité donnée effectuer ses mouvements, car il faut autant de temps à l'horloge du client pour rattraper son retard.
J'ai réussi à surmonter cela en calculant la différence entre l'horloge du serveur et celle du client chaque fois qu'un instantané est reçu.
// For simplicity, don't worry about latency for now...
client_server_clock_delta = snapshot.server_timestamp - client_timestamp;
Lors de la détermination de la distance dans l'interpolation de l'entité, j'ajoute simplement la différence à l'heure actuelle du client. Le problème avec cela, cependant, est qu'il provoquera des saccades, car la différence entre les deux horloges fluctuera brusquement en raison des instantanés arrivant plus rapidement / plus lentement que les autres.
Comment synchroniser les horloges suffisamment étroitement pour que le seul retard perceptible soit celui qui est codé en dur pour l'interpolation et celui qui est causé par la latence du réseau ordinaire?
En d'autres termes, comment empêcher l'interpolation de démarrer trop tard ou trop tôt lorsque les horloges sont considérablement désynchronisées, sans introduire de secousses?
Edit: Selon Wikipedia , NTP peut être utilisé pour synchroniser les horloges sur Internet en quelques millisecondes. Cependant, le protocole semble compliqué, et peut-être exagéré pour une utilisation dans les jeux?
Réponses:
Après avoir cherché, il semble que la synchronisation des horloges de 2 ordinateurs ou plus ne soit pas une tâche triviale. Un protocole comme NTP fait du bon travail mais est censé être lent et trop complexe pour être pratique dans les jeux. En outre, il utilise UDP qui ne fonctionnera pas pour moi car je travaille avec des sockets Web, qui ne prennent pas en charge UDP.
J'ai trouvé une méthode ici cependant, qui semble relativement simple:
Il prétend synchroniser les horloges à moins de 150 ms (ou mieux) les unes des autres.
Je ne sais pas si cela suffira à mes fins, mais je n'ai pas pu trouver d'alternative plus précise.
Voici l'algorithme qu'il fournit:
Cette solution semble bien répondre à ma question, car elle synchronise l'horloge puis s'arrête, permettant au temps de s'écouler linéairement. Alors que ma méthode initiale mettait constamment à jour l'horloge, ce qui faisait que le temps sautait un peu lorsque des instantanés étaient reçus.
la source
Fondamentalement, vous ne pouvez pas réparer le monde [entier] et, finalement, vous devrez tracer la ligne.
Si le serveur et tous les clients partagent la même fréquence d'images, ils ont juste besoin de se synchroniser lors de la connexion, et parfois par la suite, en particulier après un événement de latence. La latence n'affecte pas le flux de temps ni la capacité du PC à le mesurer. Dans de nombreux cas, plutôt que d'interpoler, vous devez extrapoler. Cela crée des effets tout aussi indésirables mais, encore une fois, c'est ce que c'est et vous devez choisir le moins de tous les maux disponibles.
Considérez que dans de nombreux MMO populaires, les joueurs en retard sont visuellement évidents. Si vous les voyez fonctionner en place, directement dans un mur, votre client extrapole. Lorsque votre client reçoit les nouvelles données, le joueur (sur son client) peut avoir parcouru une distance considérable et va se «coller» ou se téléporter vers un nouvel emplacement (la «secousse» que vous avez mentionnée?). Cela se produit même dans les grands jeux de marque.
Techniquement, c'est un problème avec l'infrastructure réseau du joueur, pas avec votre jeu. Le point auquel il passe de l'un à l'autre est la ligne même que vous devez tracer. Votre code, sur 3 ordinateurs distincts, devrait plus ou moins enregistrer le même temps écoulé. Si vous ne recevez pas de mise à jour, cela ne devrait pas affecter votre fréquence d'images Update (); au contraire, cela devrait être plus rapide car il y a probablement moins à mettre à jour.
"Si vous avez une mauvaise connexion Internet, vous ne pouvez pas jouer à ce jeu de manière compétitive."
Ce n'est pas de l'argent ou un bug.
la source