Je crée mon premier jeu en ligne en utilisant socket.io, et j'aimerais que ce soit un jeu multijoueur en temps réel comme agar.io ou diep.io.
Mais j'ai rencontré le problème d'essayer de comprendre comment faire fonctionner tous les ordinateurs à la même vitesse.
J'ai trois idées de modèles, mais aucune ne me semble juste, et je me demande comment les jeux vidéo normaux le font. (Vous pouvez sauter la lecture de mes idées; elles vous donnent juste un moyen de voir les problèmes que j'ai.)
Le serveur permet aux clients de s'exécuter de leur propre chef et de transmettre les mises à jour au serveur, qui les diffuse ensuite au reste des clients. Cela a pour problème que certains ordinateurs fonctionnent plus rapidement que d'autres, ce qui les laisse se mettre à jour plus rapidement et se déplacer plus rapidement sur l'écran.
Demandez au serveur de dire aux clients quand mettre à jour. Je peux ensuite attendre que le dernier client réponde (une idée terrible au cas où une personne a un ordinateur lent), attendre que le premier client réponde (encore une fois, attendre la communication avant chaque trame), ou simplement les envoyer le plus rapidement possible (ce qui semble rencontrer le même problème que le numéro 1).
Au début du jeu, demandez au serveur d'indiquer aux clients la rapidité de la mise à jour. Cela signifierait que le client serait responsable de restreindre les déplacements entre cette période. Par exemple, si quelqu'un réussit à appuyer sur un bouton deux fois au cours de cette période, il n'enverra qu'un événement de pression sur un bouton. Cela pose le problème que certaines actions seraient ignorées (telles que la double pression sur un bouton) et que l'interaction dépendrait de l'horloge du client, qui pourrait ne pas correspondre à celle du serveur. Le serveur devra alors garder une trace de chaque client et s'assurer que leurs mises à jour sont soumises au bon moment.
J'ai fait quelques recherches , mais les articles que j'ai lus ne semblent pas aborder spécifiquement ce qu'il faut faire si un client envoie des mises à jour plus rapidement que les autres clients.
Dans mon cas particulier, j'ai affaire à des gens qui ont des vitesses de clavier plus rapides (leur ordinateur enverrait plus de mises à jour de clavier que les autres ordinateurs).
Comment les programmeurs gèrent-ils généralement cela?
la source
Réponses:
Votre troisième idée semble être la plus proche de ce que je pense être la solution de l'industrie à ce genre de problème.
Ce que vous décrivez est communément appelé tiques . Dans chaque tick, un nombre fixe d'actions serait traité pour chaque client en série. Souvent, les serveurs de jeux auront des actions parallèles lorsqu'ils sont capables, mais c'est un problème beaucoup plus compliqué.
Un tick va probablement prendre la forme de 1 / N seconde, N étant le nombre de ticks par seconde, ou Tickrate. Ce tickrate peut être très très souvent ou très peu fréquent, selon votre cas d'utilisation. Ma suggestion personnelle serait d'éviter un taux de ticks supérieur à 60 ticks / seconde à moins que vous ne soyez sûr d'en avoir besoin de plus. Vous n'avez probablement pas :)
Les actions doivent être atomiques. Par exemple, dans slither.io, une action telle que bouger ne devrait pas immédiatement traiter quelque chose comme casser votre chaîne, à moins que le joueur que vous frappez n'ait déjà pris sa décision. Cela peut sembler trivial pour quelque chose au niveau des pixels, mais si vous avez affaire à un mouvement basé sur des carreaux, cela devient beaucoup plus évident et garantit l'équité. Si le joueur A se déplace vers la tuile X, Y et que le joueur B est actuellement sur cette tuile, vous devez vous assurer qu'à la fin de la graduation, le joueur B sera toujours sur cette tuile pour que toute action puisse avoir lieu entre eux.
De plus, je dirais d'éviter de faire effectuer vos calculs côté client, à moins qu'ils ne soient effectués indépendamment du côté serveur. Cela devient compliqué et coûteux avec la physique (de nombreux jeux optent pour un taux de tick inférieur pour la physique que de nombreuses autres actions et événements à cause de cela)
Pour référence, voici un bon lien pour compléter votre propre compréhension des serveurs de jeux et des réseaux multijoueurs.
Enfin, je dirais que ne laissez pas l'équité ruiner votre serveur. S'il y a des exploits qui rendent votre jeu injuste, corrigez-les. S'il s'agit d'un meilleur ordinateur ayant un léger avantage, je dirais que ce n'est pas si grave.
la source
Le système suivant garantit que tous les clients et le serveur partagent à peu près le même état de jeu à tout moment.
Avoir l'état du jeu sur le client et le serveur.
Lorsqu'un client essaie d'utiliser une commande (souris, clavier, etc. autre entrée), regardez son état du jeu si elle est valide.
Si c'est le cas, envoyez la commande au serveur, sans l'exécuter sur le client émetteur.
Lorsque le serveur reçoit la commande, regardez son état de jeu s'il est valide.
Si c'est le cas, renvoyez la commande à TOUS les clients avec la date future exacte après ce qu'elle devrait être finie d'être exécutée sur le serveur, puis exécutez les actions demandées par la commande après un délai égal au temps minimum pour envoyer la commande aux clients . puis enregistrez la date, cela permet de faire des prédictions futures. Si le temps varie trop, rendez votre système de jeu plus déterministe.
Lorsqu'un client reçoit une commande du serveur, regardez son état du jeu s'il est valide, exécutez immédiatement les actions demandées par la commande, puis regardez la date actuelle et comparez-la à la prédiction de date reçue. S'il n'est pas valide, le client n'est pas synchronisé. (Tous les clients avec une connexion similaire reçoivent en même temps)
Si la date est antérieure, vous avez rencontré un problème à l'étape précédente, corrigez-le. Si la date est légèrement après, ne rien faire. Si la date est longue après, le client n'est pas synchronisé, c'est-à-dire que le client est trop en retard.
Lorsqu'un client n'est pas synchronisé, demandez une copie de l'état de jeu complet du serveur et utilisez-le. Si cela se produit trop souvent, corrigez cela car c'est plus cher que d'envoyer des commandes.
Sur les clients, restituez les choses à l'écran UNIQUEMENT lorsqu'il n'y a plus rien à faire. Dans des scénarios simples, la fonction de rendu ne prend en entrée que l'état actuel du jeu.
En plus de cela, vous pouvez optimiser beaucoup, en utilisant des systèmes prédictifs, des commandes de regroupement, rendre uniquement les différences etc ...
La validation doit différer, par exemple, c'est au serveur de limiter les demandes de commandes / l'unité de temps.
la source
Je ne sais pas si c'est un problème de bibliothèques ou d'environnement que vous utilisez, mais je pense que vous vous en approchez totalement mal.
Dans la grande majorité des jeux multijoueurs, seul le serveur fait de vrais calculs. Les clients ne sont que des machines IO stupides où le seul problème de performance réel est de dessiner des graphiques 3D. Et dans ce cas, peu importe si le client peut fonctionner à 20 ou 200 FPS, car cela n'affecte que les visuels. Cela signifie que la «mise à jour du client» n'a absolument aucun sens. Le client peut essayer de "prédire" ce que le serveur pourrait calculer, mais cela ne fait que lisser la sensation de jeu et n'a aucun impact réel sur le jeu lui-même.
Je ne sais même pas ce que ça veut dire. La plupart des gens ne peuvent même pas suivre la vitesse des claviers bas de gamme, alors comment cela affecterait-il les performances des joueurs?
Sinon, la question semble bien trop large et vous devriez plutôt vous concentrer sur un seul problème réel, au lieu d'essayer de résoudre un problème «général» que vous pourriez même ne pas avoir.
la source