Une créature joue rarement une seule animation. Notre golem de rubis doit se tenir debout en se balançant, marcher quand il se déplace, et lever les poings quand il repère un ennemi. Un contrôleur d'animation décide laquelle de ces animations est jouée à un instant donné.
Ce guide s'appuie sur Animations d'entité. Lis-le d'abord si tu n'as pas encore créé d'animation.
Les fichiers
RP/
animations/
ruby_golem.animation.json
animation_controllers/
ruby_golem.animation_controllers.json
entity/
ruby_golem.entity.jsonImagine une série de pièces
Un contrôleur est un ensemble d'états. Imagine chaque état comme une pièce :
- La créature est toujours dans une seule pièce à la fois.
- Chaque pièce a une liste d'animations qui sont jouées tant que la créature s'y trouve.
- Chaque pièce a des portes (les transitions). Chaque porte porte une condition Molang. Quand la condition est vraie, la créature passe dans l'autre pièce.
Pour commencer, notre golem a deux pièces : idle et walking.
Étape 1 : au repos et en marche
Les fichiers de contrôleur vont dans le dossier animation_controllers du pack de ressources :
{
"format_version": "1.10.0",
"animation_controllers": {
"controller.animation.ruby_golem.move": {
"initial_state": "idle",
"states": {
"idle": {
"animations": ["idle"],
"transitions": [
{ "walking": "query.modified_move_speed > 0.1" }
],
"blend_transition": 0.2
},
"walking": {
"animations": ["walk"],
"transitions": [
{ "idle": "query.modified_move_speed < 0.05" }
],
"blend_transition": 0.2
}
}
}
}
}Lis-le comme ceci :
- Le golem commence dans
idleet joue l'animationidle. - Dès que sa vitesse dépasse 0.1, il passe dans
walkinget jouewalkà la place. - Quand il ralentit sous 0.05, il retourne dans
idle. - Chaque changement se fait en fondu sur 0,2 seconde, pour que les jambes ne sautent pas d'une position à l'autre.
Les noms dans animations sont les surnoms définis dans l'entité client, pas les longs noms en animation.. On en reparle à l'étape 2.
Deux nombres différents, exprès
L'entrée (> 0.1) et la sortie (< 0.05) utilisent des nombres différents. S'ils étaient identiques, un golem qui avance pile à cette vitesse pourrait changer de pièce à chaque image et avoir l'air de trembler.
Les champs du contrôleur
| Champ | Ce qu'il fait |
|---|---|
initial_state | L'état dans lequel la créature commence. Si tu ne le mets pas, le jeu cherche un état appelé default. |
states | Tous les états, par nom. |
Les noms de contrôleur commencent par controller.animation.. Un bon modèle est controller.animation.<mob>.<job>, comme controller.animation.ruby_golem.move.
À l'intérieur d'un état
| Champ | Ce qu'il fait |
|---|---|
animations | Ce qui est joué dans cet état. Des surnoms, ou des surnoms avec un fondu. |
transitions | Les portes de sortie de cet état, vérifiées dans l'ordre. |
blend_transition | La durée en secondes du fondu entre cet état et le suivant. |
blend_via_shortest_path | true fait tourner les os par le chemin le plus court pendant le fondu. |
on_entry | Ce qui s'exécute une fois quand la créature entre dans l'état. |
on_exit | Ce qui s'exécute une fois quand la créature quitte l'état. |
variables | Des valeurs calculées pour cet état, voir plus bas. |
particle_effects | Les particules à afficher pendant cet état. |
sound_effects | Les sons à jouer en entrant dans cet état. |
Les particules et les sons sont expliqués dans Événements d'animation.
Les transitions
transitions est une liste. Chaque entrée a une clé (l'état de destination) et une condition Molang :
"transitions": [
{ "alert": "query.has_target" },
{ "swimming": "query.is_in_water" },
{ "idle": "query.modified_move_speed < 0.05" }
]- Les conditions sont vérifiées de haut en bas. La première qui est vraie l'emporte.
- Il n'y a qu'une seule transition par image.
- Si aucune n'est vraie, la créature reste où elle est.
Mets donc la porte la plus importante en premier. Ici, repérer un ennemi passe avant tout le reste.
Les fondus à l'intérieur d'un état
Un état peut jouer plusieurs animations en même temps. Chacune peut avoir une valeur de fondu, exactement comme dans scripts.animate :
"walking": {
"animations": [
"idle",
{ "walk": "query.modified_move_speed" }
]
}Un golem lent montre un peu de marche par-dessus son balancement. Un golem rapide montre la marche complète.
Étape 2 : le relier à la créature
Un contrôleur se déclare dans la liste animations de l'entité client, de la même façon qu'une animation. Ensuite, tu le joues depuis scripts.animate :
"animations": {
"idle": "animation.ruby_golem.idle",
"walk": "animation.ruby_golem.walk",
"fists_up": "animation.ruby_golem.fists_up",
"look_at_target": "animation.common.look_at_target",
"move_controller": "controller.animation.ruby_golem.move"
},
"scripts": {
"animate": [
"look_at_target",
"move_controller"
]
}Remarque que idle et walk ne sont plus dans animate. C'est le contrôleur qui les joue maintenant. Si tu les laisses, ils sont joués deux fois.
Tu peux faire tourner plusieurs contrôleurs côte à côte. Chacun garde son propre état actuel. Une organisation courante : un contrôleur pour les jambes et le corps, un autre pour les bras.
Étape 3 : un état d'alerte
Faisons lever les poings au golem quand il a une cible. Ajoute un troisième état et une porte qui y mène depuis les deux autres états :
"states": {
"idle": {
"animations": ["idle"],
"transitions": [
{ "alert": "query.has_target" },
{ "walking": "query.modified_move_speed > 0.1" }
],
"blend_transition": 0.2
},
"walking": {
"animations": ["walk"],
"transitions": [
{ "alert": "query.has_target" },
{ "idle": "query.modified_move_speed < 0.05" }
],
"blend_transition": 0.2
},
"alert": {
"animations": [
"fists_up",
{ "walk": "query.modified_move_speed" }
],
"transitions": [
{ "idle": "!query.has_target" }
],
"blend_transition": 0.3
}
}Dans alert, le golem garde les poings levés et continue de marcher quand il te poursuit.
Attendre la fin d'une animation
Certaines animations doivent être jouées une seule fois, du début à la fin, comme un rugissement. Deux requêtes t'aident pour ça :
| Requête | Vraie quand |
|---|---|
query.all_animations_finished | Toutes les animations de l'état sont arrivées à leur fin |
query.any_animation_finished | Au moins l'une d'elles est arrivée à sa fin |
"roar": {
"animations": ["roar"],
"transitions": [
{ "alert": "query.all_animations_finished" }
]
}Elles ne fonctionnent qu'avec des animations qui ne bouclent pas. Une animation en boucle ne se termine jamais.
on_entry et on_exit
on_entry s'exécute une fois quand la créature entre dans un état, on_exit une fois quand elle en sort. Dans un pack de ressources, ils exécutent du Molang, ce qui est pratique pour définir des variables :
"alert": {
"on_entry": ["variable.times_alerted = (variable.times_alerted ?? 0) + 1;"],
"on_exit": ["variable.calm_since = query.life_time;"],
"animations": ["fists_up"],
"transitions": [{ "idle": "!query.has_target" }]
}Dans un pack de comportements, ces mêmes listes peuvent aussi exécuter des commandes et des événements d'entité. Voir Événements d'animation.
Les variables d'état
Un état peut calculer ses propres valeurs avec variables. La partie pratique, c'est remap_curve : elle transforme une plage de nombres en une autre.
"walking": {
"variables": {
"swing": {
"input": "query.modified_move_speed",
"remap_curve": {
"0.0": 0.3,
"1.0": 1.0
}
}
},
"animations": [{ "walk": "variable.swing" }]
}Quand la vitesse vaut 0, variable.swing vaut 0.3. Quand elle vaut 1, il vaut 1.0. Entre les deux, le jeu trace une ligne droite. Ainsi, même un golem lent montre un peu de marche.
Quand quelque chose ne va pas
| Ce que tu vois | Cause la plus probable |
|---|---|
| Rien n'est joué | Le contrôleur est dans animations mais pas dans scripts.animate |
| Une animation est deux fois trop forte | Elle est à la fois dans scripts.animate et dans un état du contrôleur |
| La créature reste bloquée dans un état | Aucune transition de sortie n'est jamais vraie. Vérifie le Molang de ses portes |
| Une animation à jouer une fois ne finit jamais | Elle a "loop": true, donc all_animations_finished n'est jamais vrai |
| La créature clignote entre deux états | Les conditions d'entrée et de sortie se chevauchent. Utilise deux nombres différents |
| Le Content Log dit qu'un état est introuvable | Une transition pointe vers un nom d'état mal orthographié |
Tu trouveras plus d'aide dans Dépannage.
Et ensuite
- Choisis les textures et masque des parties du modèle avec les Contrôleurs de rendu.
- Déclenche des sons, des particules et des commandes avec les Événements d'animation.
- Découvre d'autres astuces Molang dans le guide Molang.