Je sais que ma configuration multijoueur super simple n'est probablement pas une bonne idée, mais pourquoi?


11

Je fais un simple petit MOBA juste pour le plaisir. Je faisais tout en solo puis j'ai réalisé "oh merde je devrais probablement ajouter du multijoueur, hein."

Je n'avais jamais rien fait avec le réseau auparavant, donc apprendre à intégrer Lidgren dans mon jeu était amusant et génial. Le fait est que je sais à peu près comment je fais les choses est faux, car ce n'est pas assez robuste pour les jeux grand public à utiliser, à ma connaissance, mais qu'est-ce qui ne va pas?

Ce que je fais, c'est, fondamentalement, chaque fois qu'un joueur fait une action, il envoie un message au serveur disant "hé, je viens de faire cette chose." Le serveur et le client exécutent tous deux la même simulation. Le serveur envoie ensuite un message à tous les autres clients leur disant que ce type a fait cette chose.

Dans la plupart des cas, sauf dans quelques cas, lorsqu'un joueur fait quelque chose, le client suppose que c'est cool et va de l'avant avec lui-même. Donc, lorsque vous faites un clic droit quelque part pour vous y déplacer, le client de ce joueur commence simplement à déplacer son gars là-bas, puis envoie un message au serveur pour lui en parler.

Donc en gros:

  • Le joueur 1 lance un sort pour le faire bouger 100% plus vite pendant six secondes
  • Le client local du joueur 1 ajoute ce buff à son objet Unité
  • Le client du joueur 1 envoie un message au serveur disant "hé je viens de lancer ce sort"
  • Le serveur s'assure qu'il avait vraiment assez de mana pour lancer ce sort, et si c'est le cas, ajoute ce buff à la copie du serveur de cet objet Unit
  • Le serveur envoie un message à tous les autres clients disant "hé ce gars vient de lancer ce sort"
  • Tous les autres clients reçoivent le message et disent "ah ok cool" et ajoutent ce buff à leur objet Unit local pour ce joueur

J'ai parcouru des trucs pour voir comment les gros jeux font du multijoueur, et c'est un peu déroutant pour quelqu'un qui commence à peine à essayer ce truc, mais il semble que le moteur source envoie un paquet contenant toutes les modifications de tout dans le monde à chaque tique? Encore une fois, totalement nouveau pour ce genre de choses, mais pouvez-vous vraiment pousser autant de données aussi fréquemment?

Désolé si c'est un peu aléatoire, mais au fond, je me demandais pourquoi mon système plus simple n'est pas la bonne voie à suivre, car si c'était le cas, d'autres jeux l'utiliseraient, non?


6
Une étape qui vous manque est que le serveur envoie également ce message au client d'origine (pas seulement à tout le monde) pour confirmer ou refuser le résultat de la simulation, le client d'origine continue alors ou s'adapte à la nouvelle réalité. En dehors de cela, cette méthode est très bien et les autres réponses ci-dessous vous aideront à mieux comprendre d'autres aspects.
Patrick Hughes

1
Ce qui est génial, c'est que le reste d'entre nous a un espoir raisonnable que le réseau n'est pas si difficile. C'est faisable.
ashes999

Réponses:


12

En plus de la réponse de Byte56, il y a quelques autres choses à considérer:

Comment allez-vous communiquer entre les clients sur le mouvement des joueurs? Contrairement à la plupart des autres actions des joueurs, qui ont tendance à être des événements isolés et probablement peu fréquents, le mouvement est continu. Il y a une limite à la vitesse à laquelle vous pouvez (et souhaitez, d'ailleurs) envoyer et recevoir des mises à jour. La prédiction côté client mentionnée par Byte56 implique généralement des mises à jour périodiques sur la position et la vitesse du client. Le client interpole ensuite localement entre eux, en utilisant quelque chose comme une spline cubique .

Un deuxième problème, qui revient aux précédents, est que UDP n'a pas de livraison garantie. Vous ne pouvez pas être certain que chaque message que vous envoyez arrive ou arrive dans le bon ordre. Vous pouvez envoyer des paquets 1, 2 et 3, et le serveur en reçoit 3 puis 1 et non 2. Souvent, ils seront dans le bon ordre, et souvent ils arriveront, mais pas toujours. Vous avez donc besoin d'un système résistant à la perte de paquets. Un simple système de confirmation suffit. Un champ de bits est généralement utilisé pour indiquer à l'autre nœud s'il a reçu les 32 derniers messages (pour un entier 32 bits) et quel était le dernier message reçu. De cette façon, vous pouvez étiqueter les messages comme critiques ou non et les renvoyer s'ils n'en reçoivent pas. Il y a une discussion assez décente à ce sujet ici .

Vous devez également garder à l'esprit, lors de cette opération, que vos clients ne seront pas synchronisés les uns avec les autres. Chacun montrera les autres joueurs interpolant entre leurs deux trames réseau précédentes pendant que vous travaillez sur la suivante, dans le meilleur des cas. Vous avez donc besoin d'un système qui prend en compte (assez) que ce qu'un joueur a vu quand il a effectué une action n'était pas l'état réel du jeu quand il a fait cette action. Il réagissait à un ancien état de jeu désynchronisé.

Enfin, si ce jeu est destiné à être compétitif, vous devez également vous soucier de la triche. Ainsi, dans la mesure du possible (et raisonnable), vous devez vous méfier des clients et vérifier que leurs actions étaient possibles. "Non, vous ne pouvez pas traverser ce mur. Non, vous ne pouvez pas marcher plus vite que votre vitesse de course. Non, vous ne pouvez pas prétendre avoir atteint cette cible." etc.

Pour plus d'idées, je vous recommande de parcourir les autres articles dans ce deuxième lien.

Bonne chance!


6

Ce que vous décrivez est essentiellement une prédiction côté client , mais vous ne dites pas ce qui se passe lorsque le serveur et le client sont en désaccord.

Cela a évolué à partir du moment où le client n'était qu'un terminal stupide, envoyant ses entrées au serveur, et le serveur a informé le client du résultat. Cependant, une fois que les jeux ont dépassé le LAN (et souvent avant), la latence était perceptible dans cette situation. Ce que vous décrivez, la prédiction côté client a été introduite pour résoudre ce problème. Maintenant, le client simule également le mouvement en attendant que le serveur réponde. Ensuite, ils parviennent à un accord sur le résultat. Le serveur étant l'autorité.

Les prochaines étapes sont la façon dont vous réagissez aux désaccords. Si vous n'avez rien en place pour cela, vous obtiendrez l'élastique ou le téléportage du client lorsque le client et le serveur ne sont pas d'accord.


5

Horaire. Les autres réponses ne mentionnent pas le timing des événements sur le serveur et les différents clients. Selon le jeu, cela pourrait être quelque chose à surveiller. La latence (alias Lag) introduit un délai variable entre l'envoi d'un paquet et sa réception. Le temps peut être difficile, mais je vais essayer d'expliquer les problèmes potentiels du mieux que je peux. Il y a des jeux qui peuvent se débrouiller sans se soucier de cela, mais voici un exemple simple où cela peut causer des problèmes.

Supposons que tout le monde agisse sur les paquets dès leur arrivée.

@ Time 0 (wall time), Player 1 puts up a shield   (Message has been sent, but not received by anyone)
@ Time 1, Player 2 shoots player 1   (Message has been sent, but not received by anyone)

Supposons que les temps 0 (T0) et T1 sont proches l'un de l'autre.

Ce qui se passe ensuite dépend de qui regarde cela et de l'ordre dans lequel les paquets arrivent sur le serveur. Le serveur doit toujours avoir le dernier mot. SI le serveur reçoit les paquets dans l'ordre indiqué ci-dessus, alors le serveur appliquera le bouclier avant le coup et le joueur 1 (P1) survivra. Du point de vue de P1, après avoir installé le bouclier lui-même, il verra le bouclier avant le tir et survivra. Mais qu'en est-P2? Ils verront le coup tout de suite parce qu'ils l'ont tiré, mais verront-ils d'abord le bouclier? Si (T0 + latency between P1 and the server + the latency between the server and P2) > T1, le bouclier apparaîtra après le tir, et P2 pensera que leur tir a tué P1. Le serveur devra en quelque sorte corriger cette situation.

Si toutefois le serveur reçoit les paquets dans l'ordre inverse (ce qui est tout à fait possible, même si T0 <T1), alors l'inverse se produit. P1 est faux (et mort), tandis que P2 est correct (et victorieux).

Il existe plusieurs façons de gérer des situations comme celle-ci, mais la plus simple consiste à laisser le serveur faire tout. Vous pouvez essayer de simuler cela sur le client, mais n'autorisez aucune action permanente, comme la mort. Les joueurs devront attendre les confirmations importantes qui changeront la donne du serveur.

L'envoi d'un horodatage avec des actions peut être bénéfique. SI vous faites principalement confiance aux clients, vous pouvez utiliser ces horodatages pour déterminer quelle action s'est produite en premier, au lieu de suivre notre première hypothèse. Cela peut être délicat, car la réception de messages du passé signifie généralement que vous devez pouvoir inverser le temps.

Le temps est amusant hein? Peu importe ce que vous finissez par faire, il est utile d'être conscient de ces problèmes de temps.

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.