J'étais assez curieux de savoir comment la relecture pourrait être implémentée dans un jeu.
Au départ, je pensais qu'il y aurait juste une liste de commandes de chaque action de joueur / ai qui a été prise dans le jeu, puis il «rejoue» le jeu et laisse le moteur rendre comme d'habitude. Cependant, je l' ai regardé rejoue dans les jeux FPS / RTS, et sur une inspection minutieuse même des choses comme les particules et problèmes graphiques / sonores sont compatibles (et les glitches sont généralement en constante).
Alors, comment cela se passe-t-il. Dans les jeux à angle de caméra fixe, je pensais qu'il pourrait simplement écrire chaque image de la scène entière dans un flux qui est stocké, puis rejoue simplement le flux, mais cela ne semble pas suffisant pour les jeux qui vous permettent de faire une pause et de déplacer la caméra. autour. Vous auriez à stocker les emplacements de tout dans la scène à tout moment (non?). Donc, pour des choses comme les particules, c'est beaucoup de données à pousser, ce qui semble être un tirage important sur les performances du jeu tout en jouant.
la source
Réponses:
Je pense que votre première pensée était correcte. Pour créer une relecture, vous stockez toutes les entrées reçues de l'utilisateur (avec le numéro de l'image à laquelle elles ont été reçues) ainsi que les valeurs initiales de tout générateur de nombres aléatoires. Pour rejouer le jeu, vous réinitialisez vos PRNG en utilisant les graines sauvegardées et alimentez le moteur de jeu la même séquence d'entrée (synchronisée avec les numéros d'image). Étant donné que de nombreux jeux mettront à jour l'état du jeu en fonction du temps qui s'écoule entre les images, vous devrez peut-être également stocker la longueur de chaque image.
la source
Starcraft et Starcraft: Brood War avaient une fonction de relecture. Une fois le match terminé, vous pouvez choisir d'enregistrer la rediffusion pour l'afficher plus tard. Lors de la relecture, vous pouvez faire défiler la carte et cliquer sur les unités et les bâtiments, mais ne pas modifier leurs comportements.
Je me souviens avoir regardé une fois une rediffusion d'un match qui avait été joué dans le jeu original, mais la rediffusion était visionnée dans Brood War. Pour ceux qui ne sont pas familiers, Brood War contient toutes les unités et bâtiments d'origine, ainsi qu'une variété de nouveaux. Dans le jeu original, le joueur avait vaincu l'ordinateur en créant des unités que l'ordinateur ne pouvait pas facilement contrer. Quand j'ai joué la rediffusion dans Brood War, l'ordinateur avait accès à différentes unités, qu'il a créées et utilisées pour vaincre le joueur. Ainsi, le même fichier de relecture a abouti à un gagnant différent selon la version de Starcraft qui jouait le fichier.
J'ai toujours trouvé le concept fascinant. Il semblerait que la fonction de relecture fonctionnait en enregistrant toutes les entrées du lecteur et supposait que l'ordinateur répondrait à ces stimuli exactement de la même manière à chaque fois. Lorsque les entrées du joueur ont été introduites dans le replayer Starcraft original, le jeu s'est déroulé exactement comme il l'a fait dans le match original. Lorsque la même entrée exacte a été introduite dans le replayer Brood War, l'ordinateur a réagi différemment, a créé des unités plus fortes et a remporté la partie.
Quelque chose à garder à l'esprit si vous écrivez un moteur de relecture.
la source
Il existe deux méthodes principales:
Cela dépend de ce que vous voulez faire. Parfois, le stockage des événements est préférable, car cela prend généralement beaucoup moins de mémoire. D'un autre côté, si vous souhaitez fournir des rediffusions qui peuvent être jouées à différentes vitesses et à partir de différents points de départ, il est préférable de stocker les états. Lors du stockage des états, vous pouvez également décider de les stocker après chaque événement ou de les stocker seulement 12 ou 25 fois par seconde - cela peut réduire la taille de votre relecture et faciliter leur retour / avance rapide.
Notez que "état" ne signifie pas état graphique. Plus quelque chose comme les positions des unités, l'état des ressources et ainsi de suite. Des choses comme les graphiques, les systèmes de particules, etc. sont généralement déterministes et peuvent être stockées sous la forme "animation X, temps Y: Z".
Parfois, les replays sont utilisés comme système anti-tricheur. Ensuite, stocker les événements est probablement le meilleur ici.
la source
Techniquement, vous devez écrire votre moteur pour qu'il soit déterministe, ce n'est pas un hasard. En supposant qu'un personnage dans le jeu vise le bras d'un adversaire et tire une arme, alors le même montant de dégâts doit être appliqué à l'adversaire dans tous les cas.
En supposant qu'une bombe explose à l'emplacement X, les particules produites par cette explosion devraient toujours donner le même résultat visuel. Si vous avez besoin du caractère aléatoire, créez un ensemble de nombres aléatoires, sélectionnez une valeur de départ lorsque le jeu est joué et enregistrez cette valeur de départ dans la relecture.
En général, avoir du hasard dans un jeu est une mauvaise idée. Même pour des choses comme le multijoueur, vous ne pouvez pas avoir la moitié de vos joueurs capables de voir autour d'une explosion alors que les autres ne le peuvent pas simplement parce qu'ils n'ont pas obtenu la bonne valeur aléatoire.
Rendez tout déterministe, et tout devrait aller bien.
la source
Étant donné l' état initial et une série d'actions avec des horodatages , il suffit de parcourir la séquence car les actions enregistrées sont censées se produire et être relues.
Pour que les événements aléatoires se reproduisent exactement de la même manière, utilisez des nombres pseudo-aléatoires prédéfinis et enregistrez la valeur de départ dans le fichier de relecture.
Tant que vous utilisez le même algorithme pour générer les nombres aléatoires à partir de la graine, vous pouvez recréer tous les événements tels qu'ils se sont produits dans le jeu en direct sans avoir besoin d'instantanés complets de l'état du jeu.
Cela nécessitera que les rediffusions soient regardées séquentiellement , mais c'est assez normal pour les rediffusions de jeu (voir Starcraft 2). Si vous souhaitez autoriser l'accès aléatoire à la chronologie, vous pouvez prendre des instantanés de l'état complet à des intervalles définis (par exemple, toutes les minutes), pour sauter dans la chronologie avec une granularité définie.
la source
NVidia PhysX (un moteur de simulation physique souvent utilisé dans les jeux) est capable d'enregistrer l'état complet de la scène physique au fil du temps. Cela intègre toutes les entrées de pilotage du moteur de jeu, ce qui signifie que vous n'avez pas besoin de suivre les graines de nombres aléatoires comme d'autres l'ont suggéré. Si vous effectuez ce vidage de scène, vous pouvez le rejouer dans un outil externe (fourni par NVidia), ce qui est très pratique pour dépister les problèmes avec vos modèles physiques. Cependant, vous pouvez également utiliser le même flux physique pour piloter votre moteur graphique, ce qui vous permettrait alors d'avoir un contrôle normal de la caméra, car seule la physique pilotant les graphiques a été enregistrée. Dans de nombreux jeux, cela inclut les effets de particules (PhysX comprend des systèmes de particules très sophistiqués.) En ce qui concerne le son, je suppose qu'il est enregistré textuellement (sous forme de flux sonore), mais je '
la source
Votre idée originale est juste, et pour les effets vraiment complexes, ils ne se souviennent pas exclusivement. Par exemple, le système de relecture de Warcraft 3 ne stocke pas l'état des animations, ou des effets de particules dans le cas d'effets aléatoires, etc. En outre, la plupart des choses peuvent être calculées par ordinateur à partir d'un point de départ de manière déterministe, donc pour la plupart des systèmes qui utilisent des variables aléatoires (une explosion de particules qui donne un décalage aléatoire, par exemple), tout ce dont vous auriez besoin est l'heure de l'effet et la graine aléatoire. Vous pourriez alors régénérer l'effet sans vraiment savoir à quoi il finira par ressembler ... sachant qu'il passe par un chemin de code déterministe.
En y pensant purement conceptuellement, pour rejouer une chronologie des événements, tout ce dont vous avez besoin sont les actions de l'utilisateur. Le programme réagira exactement de la même manière, sauf dans le cas de variables aléatoires. Dans ce scénario, vous pouvez soit ignorer le caractère aléatoire (est-ce vraiment important que les effets se ressemblent EXACTEMENT, ou peuvent-ils être régénérés aléatoirement), ou stocker la valeur de départ et simuler le caractère aléatoire.
la source
Jette mes deux sous.
Dépend de ce que vous voulez, la relecture peut être effectuée via
La plupart du temps, les gens veulent une rediffusion interactive, 2. est donc la voie à suivre. Ensuite, en fonction de vos contraintes, il existe plusieurs façons d'optimiser ce processus
C'est vraiment un sujet fascinant. Je me souviens qu'un titre de lancement pour Xbox Wreckless original avait une bonne fonctionnalité de lecture. Malheureusement, à plusieurs reprises, la rediffusion aurait échoué;)
oh ouais, comment pourrait-on oublier Blinx Time Sweeper ! super rejeu interactif qui a été intégré dans la mécanique de jeu réelle!
* = il semble qu'il y ait des commentaires concernant le pas de temps. J'utilise la «simulation» ici pour capturer cette fonctionnalité. à la base, votre moteur doit être capable de produire des intervalles de temps discrets. même si une image de relecture prend plus ou moins de temps à traiter que l'original, le système doit percevoir que le même delta de temps s'est écoulé. cela signifie enregistrer le pas de temps de trame avec chaque entrée enregistrée, et fournir ce delta à votre horloge moteur.
la source
Peut-être pourriez-vous simplement enregistrer une pile de commandes envoyées par chaque joueur. Ainsi, au lieu de sauver qu'une bombe explose à un certain moment et à un certain moment, ou qu'une certaine voiture est détruite, vous sauvegardez simplement les touches envoyées par chaque joueur. Ensuite, dans la rediffusion, vous simulez simplement le jeu comme il se serait produit avec ces presses. J'ai l'impression que cela a le potentiel de prendre moins de place, mais je n'ai jamais travaillé sur un système de relecture comme celui-là.
Question intéressante, cependant. Je serais intéressé par la façon dont cela se fait dans les jeux professionnels.
la source
Dan Bryant
C'est exactement ce que j'ai pensé au début lorsque j'essayais de comprendre comment ils avaient réussi à faire en sorte que le jeu soit toujours le même à chaque fois. Avec Doom, j'ai pensé au hasard des tournages: D. Stockez n'importe quel nombre aléatoire utilisé, j'ai découvert que cela pourrait être une solution. C'était avant que je tombe sur un papier pdf sur la technologie Crysis. Certaines textures y résonnent et la disposition de l'herbe ou des arbres semblaient utiliser la pseudo-aléatoire avec des semences réversibles fixes pour que vous ne voyiez pas la disposition modifiée du bruit, des arbres et de l'herbe à chaque fois que vous regardez!
Éviter dans le même temps, de stocker des millions d'arbres et de positionner des arbres d'herbe. Apparemment, une séquence pseudo aléatoire peut rejouer la même chose à tout moment, car la logique est fixe, pour simplement créer une fausse séquence de nombres statistiquement aléatoire.
la source
Le problème d'avoir une rediffusion cohérente est le même (enfin, plus facile) que d'avoir un jeu multijoueur cohérent.
Comme d'autres l'ont mentionné précédemment, les rediffusions dans les jeux RTS sont stockées en enregistrant toutes les entrées (ce qui a un effet. Le défilement n'a aucun effet.) Le multijoueur transmet également toutes les entrées.
L'enregistrement de toutes les entrées n'est pas seulement une supposition - il existe une bibliothèque pour lire les replays de Warcraft3 avec le révèle.
l'entrée inclut les horodatages pour cette réponse.
la source
Je croirais qu'à certains moments, le jeu prendrait un instantané de l'état de tout (TOUT). Ensuite, lorsque la relecture se produit, une simple utilisation de l'interpolation linéaire peut être utilisée pour combler les «trous». Du moins, c'est ainsi que je pense que cela se ferait.
Vous avez raison de dire que l'enregistrement des entrées ne serait pas fiable / ne garantirait pas la même sortie. Le jeu doit absolument garder une trace de l'état de tous les objets (ou du moins les plus importants)
la source