De bonnes techniques pour synchroniser les actions de gameplay avec des horaires d'animation spécifiques?

10

J'ai donc rencontré un problème dans le jeu sur lequel je travaille, mais cela semble être une chose assez fondamentale qui se pose probablement dans de nombreux jeux.

Mon jeu nécessite que certaines fonctions de gameplay se produisent à un moment très précis au cours d'une animation de personnage. Et donc, comme le titre l'indique, je me demande quelles sont les bonnes techniques et stratégies fondamentales pour synchroniser les événements / fonctions / actions liés au gameplay à des points spécifiques de l'animation d'un personnage.

Voici quelques exemples simples de ce dont je parle dans différents types de jeux:

  • Votre personnage recharge son arme dans un jeu de tir . Votre personnage joue son animation de «rechargement», mais il est important que la fonction qui définit la variable currentAmmo ne soit appelée qu'au moment exact après l'échange du chargeur et l'armement de l'arme. Cela pourrait être un certain point au milieu de l'animation de rechargement.

  • Dans un RPG au tour par tour, vos personnages sont alignés face à une ligne d'ennemis. Lorsqu'il vous est ordonné d'attaquer, l'un de vos personnages court / saute vers l'un des ennemis et coupe son épée géante avant de courir / sauter à sa place debout. Vous voulez vous assurer que l' ennemi est endommagé au moment exact où l'animation coupante est jouée - un certain point entre la montée et la marche arrière.

  • Dans un jeu furtif , votre personnage peut se faufiler et interagir avec des ordinateurs et des boutons dans le monde. Il y a peut-être un bouton qui coupe l'alimentation des lumières de l'avant-poste que vous infiltrez. Lorsque le bouton d'action est enfoncé, votre personnage tend la main et appuie sur le bouton, puis revient à sa position de repos. Vous voulez que les lumières s'éteignent au point exact de l'animation 'push_button' lorsque le bouton est enfoncé.

Certes, mon cas particulier ressemble davantage au deuxième exemple , dans lequel j'ai créé une animation où mon personnage au tour par tour se précipite pendant une attaque et je veux que les dégâts soient appliqués au moment exact où l'animation semble entrer en contact. . Parce que mon jeu utilise un système au tour par tour (imaginez quelque chose comme Final Fantasy ou Fire Emblem), je veux les dégâts / guérison / magie / etc. à appliquer au bon moment pendant chaque animation de personnage même si je n'utilise pas réellement de collision / hitbox.

Je dois mentionner que je crée mon jeu dans un moteur de jeu populaire et que pour le moment je gère cela en utilisant leurs événements d' animation ou notifie pour obtenir quelque chose proche des résultats souhaités - mon personnage exécute une certaine commande et déclenche un l'animation spécifique à la commande (par exemple: 'attack_command') et les ressources d'animation pour chacune de mes commandes doivent inclure un événement d'animation / notifier un 'rappel' dans la fonction ExecuteCommand de mes personnages. En d'autres termes - le personnage indique à l'animation d'attaque de jouer, puis l'animation d'attaque émet un événement / notifie un rappel au personnage au moment exact de l'animation où les dégâts doivent être infligés.

Honnêtement, cela fonctionne pour le moment, mais cela ne me semble pas juste - comme s'il me manque une partie de la vue d'ensemble ici! Une partie de la raison pour laquelle cette méthode semble erronée est qu'elle associe la logique du jeu aux actifs d'animation; si mon actif d'animation oublie d'inclure un événement / rappel ExecuteCommand (), la commande ne s'exécutera pas correctement et du code supplémentaire est nécessaire pour vérifier si une animation de commande s'est terminée sans exécuter la commande. C'est désordonné et cela signifie que mon gameplay a une étrange dépendance sur ses actifs. Bien sûr, je veux que les dégâts se produisent à un moment précis de mon animation d'attaque, mais je me sens vraiment bizarre d'appeler du code de gameplay dans les ressources d'animation.

Alors qu'est-ce que je néglige ici? Quelles sont les bonnes techniques générales pour gérer ces types de situations dans lesquelles vous souhaitez que certaines actions de gameplay importantes se produisent à des moments spécifiques pendant les animations?

Edit: Pour clarifier, ce n'est pas une question spécifique au moteur et je ne recherche pas de conceptions / techniques spécifiques au moteur. Je m'intéresse aux techniques générales de synchronisation animation / gameplay que l'on pourrait utiliser dans vos projets de jeu quelles que soient les technologies utilisées.

MrKatSwordfish
la source
1
Je suis confus. Vous dites que vous voulez que le gameplay dépende du timing des animations, mais vous dites ensuite que vous ne voulez pas que votre gameplay dépende de vos ressources, et les animations sont un type de ressource. Comment pensez-vous que ces souhaits seront compatibles?
Anko
Je veux que certains éléments de gameplay soient synchronisés avec l'animation. Cependant, la synchronisation entre deux choses n'implique pas toujours une dépendance, non? Je suis intéressé par certaines techniques que les gens utilisent pour synchroniser leurs animations avec leur gameplay. J'ai dit ce que j'ai essayé et ce que je fais actuellement pour y parvenir - et donc ma question est, existe-t-il une technique différente / meilleure / alternative que l'on pourrait utiliser ou est-ce (événements d'animation / notifications / rappels intégrés dans le actifs) la manière standard? Est-ce cela que vous utilisez dans vos projets?
MrKatSwordfish

Réponses:

5

Pour la synchronisation, vous devez décider à qui (votre code, vos animations ou ni l'un ni l'autre) est l' autorité de chronométrage - le «rythme» que tout le monde «danse».

Différents arrangements conviennent à différents jeux:

  • Les animations sont l'autorité de synchronisation (votre configuration actuelle)

    Le code du jeu peut déclencher des animations. Lorsque les animations atteignent certains points, elles déclenchent des événements (par exemple, rechargement effectué) auxquels le code du jeu peut réagir (par exemple, réinitialiser les munitions disponibles).

    Si le timing précis des animations (indépendamment de l'état du jeu) est une partie importante de votre jeu, ou si vous souhaitez spécifiquement que vos animateurs contrôlent le timing, envisagez cette approche.

    Les outils d'animation Blender (3D) et Spine (2D) permettent à l'animateur de définir les événements auxquels le code de jeu peut s'abonner.

  • Le code est l'autorité de chronométrage

    Inverse de ce qui précède: les événements qui se produisent dans le monde du jeu (par exemple, le joueur qui choisit de recharger son arme) entraînent l'exécution d'animations et la transmission de paramètres (par exemple le temps jusqu'à ce que le rechargement soit terminé). Chaque animation utilise les paramètres fournis pour modifier son apparence (par exemple, exécuter l'animation à une vitesse appropriée de sorte que la "partie rechargée" se produise lorsqu'elle est spécifiée).

    Les animations peuvent également écouter les événements du jeu (par exemple, le joueur annule le rechargement ou le joueur s'accroupit pendant le rechargement) et modifier leur apparence en conséquence.

    Si vos animations peuvent se permettre d'être flexibles sur le timing, votre jeu s'appuie fortement sur du contenu généré de manière procédurale, ou si vous souhaitez spécifiquement que vos programmeurs contrôlent le timing, envisagez cette approche.

    Les animations des personnages de Overgrowth sont largement structurées de cette façon: David Rosen l'explique dans son discours sur GDC 14 (voir spécifiquement lessegments Movement et Movement Continued ).

  • Calendrier implicite (autorité externe)

    Dans les jeux de rythme ou dans d'autres situations où le timing est contrôlé à partir d'une source externe (dans les jeux de rythme, le rythme du morceau de musique), il peut être judicieux de modéliser les choses en tant que telles. Le code de jeu et les animations peuvent à la fois lire un horodatage global et un état de jeu, puis se comporter en conséquence sans communiquer.

    Si votre état de jeu et vos animations dépendent largement d'une autorité de chronométrage externe, envisagez cette approche.

Vous pouvez bien sûr vouloir utiliser différentes approches pour différents systèmes dans votre jeu. (Par exemple, les jeux de rythme utilisent fréquemment le rythme de la chanson comme autorité externe, mais les animations écoutent toujours les événements d'interaction des joueurs pour annuler ou modifier l'apparence des notes tenues.)

Anko
la source
0

J'ai lu quelque part que presque tous les problèmes de calcul peuvent être résolus avec une couche d'abstraction supplémentaire, et je ne vois pas votre cas être différent.

Pour cette exigence, je vois généralement une couche pour contrôler l'état du personnage. De cette façon, le personnage aura une animation et un état actuels. Chacun avec sa propre responsabilité.

L'animation n'est responsable que du visuel et l'état gère la logique spécifique au jeu pour cette action.

Dans mon jeu de combat, l'état est un objet qui hérite de la classe BaseState et possède une méthode Update (). Chaque personnage possède une collection d'états, mais un seul peut être attribué à la fois. Et la méthode Update () de l'état actuel est appelée une fois par trame.

C'est à l'intérieur de la mise à jour () de l'état où je fais toute cette logique: définir la vitesse du caractère à une image spécifique, augmenter / diminuer la santé, etc.

Emir Lima
la source