À quelle fréquence enregistrer l'état du joueur dans les jeux en ligne persistants?

9

Dans les jeux en ligne, les gens préfèrent se connecter et se déconnecter quand ils le souhaitent. Habituellement, leurs réalisations de jeu sont enregistrées de manière transparente sur le serveur. Ce n'est pas si difficile à réaliser, mais je me demande comment faire de manière efficace, logique et à grande échelle.

Est-il judicieux d'enregistrer les coordonnées et l'état du joueur à chaque fois qu'il l'envoie? Mon serveur node.js peut le faire facilement sans bloquer une réponse, et je veux utiliser une base de données Mongo, mais peut-être qu'il est plus approprié de le faire une fois par seconde et dans un événement à l'échelle du serveur, en collectant tout à la fois?

Lanbo
la source
Je sauvegarde l'état du jeu toutes les 10 secondes. Je pense que cela suffit, cela passe inaperçu (et j'exécute mon serveur MMORPG sur mon netbook qui a 512 Mo de RAM).
jcora

Réponses:

10

Je pense à un MMORPG traditionnel comme World of Warcraft.

Sauvegardez après chaque commande de chaque joueur et chose autonome (par exemple NPC)

  • Sauvegarde constante. Le serveur peut tomber en panne à tout moment, et l'état du jeu est enregistré jusqu'à ce moment (ou aussi récent que possible, de toute façon).
  • Impact sur les performances du serveur; même si elle n'est pas bloquante (c'est-à-dire sur un autre thread), même si la base de données se trouve sur un autre serveur, c'est un traitement que vous ne feriez pas autrement. S'il n'est pas bloquant comme vous le dites, alors un autre thread doit le gérer, et c'est un thread qui pourrait être occupé par autre chose.
  • Augmentation des E / S disque, augmentant ainsi le risque / taux de défaillance. Cela est particulièrement préoccupant si vous utilisez des SSD pour le stockage, compte tenu de leur durée de vie plus courte.
  • Si vous déchargez la base de données sur un autre serveur, la bande passante augmentée; cela peut être un problème si vous payez pour la bande passante, et si ce n'est pas sur une carte réseau distincte, cela consomme des ressources qui pourraient être mieux utilisées pour gérer le trafic des joueurs.
  • Que se passe-t-il si le serveur prend de plus en plus de retard dans l'enregistrement de l'état de ces commandes? C'est-à-dire si plus de commandes arrivent que ce qui peut être enregistré, alors elles s'empilent dans une file d'attente? Cette file d'attente déborde-t-elle et provoque-t-elle une erreur? Arrêtez-vous tout pour que la file d'attente puisse se rattraper?
  • Il me semble que cette approche, si elle semble simple, devrait être soigneusement planifiée. Par exemple, les commandes consécutives qui dépendent les unes des autres devront être enregistrées ensemble; sinon un échec pourrait se produire au milieu des commandes, et un seul sera enregistré mais pas l'autre. Considérez si deux joueurs exécutent un échange et que deux commandes sont enregistrées sur le disque: "ajouter 1 de l'élément au destinataire" et "soustraire 1 de l'élément à l'expéditeur". Si un échec se produit après la première commande mais avant que la deuxième commande soit enregistrée, vous avez une duplication d'élément. (si la commande est inversée, alors vous avez un article perdu)

Tout sauvegarder périodiquement

  • En cas de panne, le serveur sera quelque peu obsolète. J'espère que vous utilisez quelque chose comme une approche journalisée, donc l'instantané le plus récent sera au moins entier et cohérent, et tous les joueurs actifs seront retardés de la même durée.
  • Le système de base de données que vous utilisez peut avoir une optimisation pour la mise à jour par lots, qui est plus efficace (moins de surcharge) que la mise à jour une à la fois.
  • Si vous optez plutôt pour un système de fichiers binaires, cette méthode est très simple. Créez un nouveau fichier, videz-y la mémoire, lancez un marqueur à la fin qui signale que la sauvegarde est terminée. Une fois la sauvegarde terminée, supprimez la sauvegarde précédente (ou ne le faites pas).
  • Le processus de sauvegarde peut également avoir besoin de prendre en compte les éléments mentionnés dans le dernier point de l'autre section, tels que l'enregistrement au milieu de commandes consécutives qui ne doivent pas être interrompues. Vous pouvez choisir de verrouiller l'ensemble des données, de les vider sur le disque et de les déverrouiller, mais selon le temps que cela prend, cela pourrait entraîner une pause ou un ralentissement assez lourd dans le jeu.

Enregistrez un personnage à la déconnexion (ne sauvegardez rien d'autre)

  • La chose la plus importante pour un joueur est son personnage, qui comprend les objets qu'il possède, les compétences qu'il a acquises, sa liste d'amis, etc. S'ils tuent un monstre et que le butin est au sol devant eux et que le serveur tombe en panne, ils seront un peu navrés de ne pas avoir la chance de récupérer leur butin, mais ils s'en remettront. Il suffit donc de sauvegarder les choses importantes et de ne pas transpirer les petites choses. Ne sauvegardez pas les positions des PNJ, par exemple; si le serveur tombe en panne, quand il revient, ils apparaîtront dans la zone générale où ils devraient être. L'exception, bien sûr, est pour tous les PNJ "intelligents" qui pour une raison quelconque doivent rester à l'endroit où ils étaient quand le serveur est tombé.
  • De plus, un joueur ne devrait pas être connecté pendant trop d'heures à la fois (notez qu'ici je considère "retourner dans un lobby" comme se déconnecter). Ils auront éventuellement besoin de faire une pause dans la salle de bain ou de se nourrir ou d'être interrompus par leurs parents / amis / quoi que ce soit ou dormir. Donc, ils ne devraient vraiment pas être connectés de façon réaliste plus de 8 heures, disons, même pour le joueur le plus hardcore. Si un "joueur" est connecté pendant une très longue période de temps, il y a de fortes chances que ce soit plusieurs personnes ou un bot, et ni l'un ni l'autre n'est souhaitable ou normal.
  • En outre, votre processus de déconnexion doit déjà vérifier des éléments tels que les commandes consécutives mentionnées ci-dessus. Il devrait essentiellement déjà emballer le personnage, c'est donc évidemment un moment privilégié pour le vider sur le disque.

Pensées de clôture

  • De toute évidence, je suis en faveur de la dernière approche, mais j'ai essayé d'être impartial sur les trois.
  • Il est difficile de dire laquelle des deux premières méthodes est la plus coûteuse. Avec la première méthode, si le personnage envoie plusieurs commandes de déplacement, celles-ci seront chacune enregistrées sur le disque et écrasées, alors clairement qu'elles pourraient être regroupées en une seule. Mais avec la deuxième méthode, si vous avez environ la moitié de votre population, leurs positions sont enregistrées sur le disque même si elles sont exactement les mêmes depuis la dernière opération de sauvegarde. Dans le troisième cas, il est très possible que quelqu'un puisse se connecter et se déconnecter immédiatement, mais le plus souvent, beaucoup de choses sur le lecteur auront changé, donc le gaspillage semble être minime.
  • Gardez à l'esprit qu'il s'agit uniquement d'une sauvegarde en cas d'échec, et qu'un échec doit être absolument minimisé. C'est bien de gérer ce cas d'exception, mais au final, si le serveur tombe en panne, certaines données vont être perdues et certains joueurs vont être bouleversés. Il vous suffit donc de mettre en œuvre la méthode que vous pouvez, la plus simple ou la meilleure, et de continuer.
  • Ne comptez pas sur cela comme sauvegarde par défaut; mettez un joli bouton d'arrêt sur votre application serveur, qui ferme élégamment les connexions et écrit tout dans la base de données. Utilisez-le normalement.

Enfin, ne prenez pas ce conseil comme une vérité absolue. Je n'ai pas écrit de système de sauvegarde multijoueur. Je suis travaille sur un « jeu » en ligne, ce qui est la raison pour laquelle je l' ai pensé à cela et écrit mes pensées au- dessus, mais je ne l' ai pas obtenu à l'étape de la mise en œuvre pour l'instant. Donc, cela est écrit sans expérience réelle, mais après beaucoup de lecture et de collecte de connaissances sur le sujet.

Ricket
la source
4
D'après ce que j'ai personnellement observé, les MMO commerciaux utilisent une combinaison des trois. Les sauvegardes se produisent après des événements et des actions importants tels que les boss tués / pillés / échangés, périodiquement pour éviter que des actions non critiques ne soient manquées (et pour ne pas punir ceux qui sont connectés pendant de longues périodes), et toujours à la déconnexion. Une seule méthode ne suffit généralement pas. Presque toutes ces méthodes reposent sur une base de données de style SQL sous-jacente qui est sauvegardée et restaurée de manière transparente en cas de dysfonctionnement matériel.
NtscCobalt
@NtscCobalt - J'étais avec vous jusqu'à la "base de données de style SQL". SQL est-il vraiment une exigence? Et NoSQL?
beatgammit
@tjameson Eh bien, mon commentaire a été écrit avant d'avoir touché NoSQL. J'essayais seulement de dire que vous ne devriez pas rouler votre propre format mais de toute façon je recommanderais SQL car vous devriez connaître le schéma à l'avance (ou être paresseux et utiliser Entity-Key-Value) et la cohérence est plus importante que la possibilité de partitionner ces données. Voir stackoverflow.com/questions/7339374/… pour plus d'informations.
NtscCobalt
1

Je suppose que cela dépend du type de jeu et de la quantité de trafic entre les joueurs et le serveur.

Dans un MMORPG, cela n'aurait aucun sens de sauvegarder la position des joueurs chaque fois qu'ils envoient les informations au serveur. Il serait plus logique de mettre à jour lorsque les données actuelles du joueur sont «périmées», pour ainsi dire. Il pourrait également être utile de sauvegarder l'état du joueur lors d'événements majeurs tels que la traversée d'un nouveau territoire, la défaite d'un boss ou la sortie d'un magasin.

Dans un jeu au tour par tour, il serait certainement judicieux de sauvegarder l'état du joueur à chaque fois qu'il termine son tour ainsi qu'après le tour d'un joueur adverse (enregistrer la perte de santé, les effets des sorts, etc.).

Encore une fois, la réponse dépend entièrement de l'échelle et des capacités de votre serveur. Il s'agit de trouver le meilleur équilibre et d'optimiser autant que possible sans sacrifier la qualité.

JMellow
la source
1

Si votre seule préoccupation est quand ils se déconnectent, alors une réponse simple est de sauvegarder leur position lorsque les conditions pour eux qui n'existent plus dans le monde du jeu (en raison d'une déconnexion ou d'une déconnexion) se produisent.

Sur une note secondaire cependant, je me méfierais un peu du fait que le client signale au serveur sa position, ou tout au moins sans une forme de vérification de l'intégrité du côté serveur. Si vous avez déjà cela en place, vous pouvez probablement enregistrer cette position lors de la déconnexion ou de la déconnexion, car vous n'avez pas à vous soucier d'obtenir directement des données du client.

Lunin
la source
Oui, d'où la nécessité d'envoyer régulièrement des mises à jour au serveur sur des valeurs comme position et XP. Plus vous le laissez longtemps, plus il est discutable de savoir si le joueur a accumulé les deltas signalés ou non. Si vous limitez ces périodes "d'enregistrement", c'est beaucoup plus facile à surveiller / contrôler.
Ingénieur
Le problème de savoir quand exactement un joueur s'est déconnecté dans un jeu par navigateur de longue durée n'est en fait pas anodin.
Lanbo
Je suis d'accord que ce n'est pas anodin, mais c'est un problème que vous devez résoudre d'une manière ou d'une autre dans la plupart des jeux, même si c'est juste pour décider quand leur avatar n'apparaît plus. Une fois cela fait, il devrait être relativement simple de se connecter à ce scénario et de sauvegarder sa dernière position valide.
Lunin