Unigine 2.22 : refonte de l'animation — machines à états, blending de couches et nouveau workflow squelettique
En bref
Découvrez la refonte de l'animation d'Unigine 2.22 : machines à états, blending de couches, motion warping et guide de migration complet et détaillé.
Le workflow d'animation qui faisait fuir les développeurs Unigine
Chaque développeur Unigine s'est heurté au même mur : le renderer affiche de superbes scènes PBR à 120 fps, mais créer un simple blend idle-to-run prend une heure de bidouilles de script et de réglages manuels des os. Cet écart entre la fidélité visuelle et les outils d'animation est le secret de Polichinelle d'Unigine depuis des années, et c'est la raison pour laquelle la plupart des petites équipes qui évaluent Unigine finissent par passer leur chemin.
Avec Unigine 2.22, l'équipe a enfin attaqué ce problème de front. La version introduit un éditeur visuel de machines à états pour l'animation, le blending additif de couches avec masques par os, un pipeline d'import FBX amélioré avec mapping de squelette d'avatar, et une nouvelle API procédurale de motion warping. Pour les équipes qui utilisent Unigine pour la simulation, la visualisation architecturale ou les applications industrielles et qui bricolent leur logique d'animation en code depuis des années — cela change considérablement le travail au quotidien.
Ce guide détaille ce qui a réellement changé, comment migrer de l'ancienne approche très scriptée vers les nouveaux outils de machines à états, et où les cas limites font le plus mal.
Ce qui a changé dans le système d'animation d'Unigine 2.22
L'ancienne méthode : une logique d'animation pilotée par script
Avant la 2.22, déclencher une transition d'animation dans Unigine signifiait écrire la logique soi-même :
// UnigineScript — old pattern, pre-2.22
AnimLayer idle_layer = new AnimLayer();
idle_layer.SetAnimation("idle.anim");
idle_layer.Loop = true;
AnimLayer run_layer = new AnimLayer();
run_layer.SetAnimation("run.anim");
run_layer.Loop = true;
void update(float speed) {
float blend = clamp(speed / 6.0, 0.0, 1.0);
if (blend > 0.01f) {
idle_layer.SetWeight(1.0 - blend);
run_layer.SetWeight(blend);
} else {
idle_layer.SetWeight(1.0);
run_layer.SetWeight(0.0);
}
}
Cela fonctionne pour un système à deux états, mais l'étendre à l'accroupissement, au saut, à la visée, au sprint et à 15 variantes d'attaque devient vite ingérable. Chaque équipe finit avec une machine à états artisanale en script, et chaque équipe finit par lutter contre les pops de transition et les bugs de blending.
L'approche 2.22 : des machines à états déclaratives
Unigine 2.22 introduit le système AnimationGraph — un éditeur de machines à états basé sur des nœuds, intégré à l'Unigine Editor, accompagné d'une API de script pour le contrôle à l'exécution. Les états correspondent à des clips d'animation ou à des espaces de blend. Les transitions définissent les conditions et les durées. Le moteur gère en interne l'interpolation, le blending d'interruption et la composition des couches.
Les améliorations clés :
- Éditeur visuel de machines à états — définissez états, transitions et conditions dans l'éditeur avec un aperçu du graphe
- Empilement de couches avec masques osseux — blend de la visée du haut du corps par-dessus la locomotion du bas du corps à l'aide de groupes d'os nommés
- Support de l'animation additive — appliquez l'inclinaison, le regard et le recul comme des offsets plutôt que des remplacements complets de pose
- Import FBX amélioré — mapping de squelette d'avatar qui préserve les hiérarchies osseuses entre variantes de personnages
- Motion warping — le root motion peut être redirigé et blendé à l'exécution pour les escalades, les franchissements et les transitions de couverture
Mise en place du nouveau pipeline d'animation étape par étape
Étape 1 : Définir le squelette de votre avatar
Le squelette d'avatar est la pièce maîtresse du workflow 2.22. C'est un modèle d'os nommé qui fait correspondre les maillages squelettiques des outils DCC (Blender, Maya, 3ds Max) à un squelette canonique référencé par la machine à états d'animation.
Si vous sautez cette étape — et beaucoup de développeurs qui découvrent le système le font — les animations se joueront sur les mauvais os ou ne se joueront pas du tout. Le moteur ne lèvera pas d'erreur ; il utilisera silencieusement le premier os trouvé avec un nom correspondant, ce qui provoque d'étranges artefacts de rendu.
Dans le panneau Skeleton Asset de l'éditeur, définissez votre avatar :
// Avatar definition in Unigine's data format
avatar {
name = "humanoid_standard";
bones {
root = "Hips";
left_arm = "LeftArm";
right_arm = "RightArm";
left_leg = "LeftLeg";
right_leg = "RightLeg";
spine = "Spine";
head = "Head";
}
}
Chaque asset de personnage de votre projet partage cette définition d'avatar. Lorsque vous importez un nouvel humanoïde, vous faites correspondre ses noms d'os aux noms de l'avatar une seule fois, et chaque clip d'animation de chaque personnage fonctionne avec les animations de tous les autres personnages. Le temps d'installation typique pour ce mapping est de 10 à 15 minutes par personnage, contre l'ancienne approche qui consistait à nommer manuellement les points d'ancrage pour chaque clip d'animation, ce qui prenait 30 à 60 minutes par personnage et cassait à chaque retargeting.
Étape 2 : Construire la machine à états dans l'éditeur
Ouvrez l'éditeur AnimationGraph depuis le navigateur d'assets d'Unigine 2.22. Pour un contrôleur de personnage de base, vous aurez besoin au minimum de :
- État Idle — animation idle en boucle, état d'entrée
- Espace de blend Locomotion — blend 2D de marche/jogging/course basé sur des paramètres de vitesse et de direction
- État Jump — début de saut non bouclé et transitions en l'air
- État Land — récupération par étapes avec transition interruptible vers la locomotion
Chaque état référence un clip d'animation ou un espace de blend. Les transitions relient les états avec des paramètres de condition — des floats, des bools ou des triggers que vous définissez depuis le code à l'exécution.
[Idle] --(speed > 0.1)--> [Locomotion]
[Locomotion] --(is_jumping == true)--> [Jump]
[Jump] --(on_ground == true)--> [Land]
[Land] --(land_finished == true)--> [Idle]
[Damage_Taken] --(hit_received == true)--> [Flinch]
[Flinch] --(flinch_finished == true)--> [Idle]
Étape 3 : Le piloter depuis le code
Le côté script est considérablement simplifié. Au lieu de calculer manuellement les poids de blend, vous poussez les valeurs des paramètres à chaque frame :
// UnigineScript — driving the 2.22 AnimationGraph
ObjectMeshSkinned character_node;
AnimationGraph anim_graph;
int init() {
character_node = node_cast(engine.editor.getNode("player_character"));
anim_graph = new AnimationGraph(character_node);
anim_graph.Load("animations/player_graph.animgraph");
return 1;
}
int update() {
float speed = length(character_node.getPositionVelocity());
bool is_jumping = !character_node.isOnGround();
anim_graph.SetFloat("speed", speed);
anim_graph.SetFloat("direction", character_node.getTurnAngle());
anim_graph.SetBool("is_jumping", is_jumping);
anim_graph.SetBool("on_ground", character_node.isOnGround());
if (received_damage) {
anim_graph.Trigger("hit_received");
received_damage = false;
}
anim_graph.Update();
return 1;
}
L'ancienne version de ce code faisait 120 à 180 lignes de gestion manuelle du blend. La nouvelle version fait moins de 30 lignes car la machine à états, le blending et la logique de transition vivent dans l'asset graph.
Étape 4 : Configurer le blending de couches pour le haut/bas du corps
Pour un personnage qui doit viser en courant, vous avez besoin de deux couches d'animation blendées avec des masques osseux. Dans l'éditeur AnimationGraph 2.22 :
Couche 0 (base) : machine à états Locomotion — affecte les hanches, les jambes, le tronc de la colonne
Couche 1 (override haut du corps) : espace de blend Aim — affecte la colonne, les bras, la tête
Couche 2 (additive) : animation de recul — offset additif sur le bras droit et la colonne
Les masques osseux utilisent les groupes d'os de l'avatar définis à l'étape 1. Le poids de blend du masque définit à quel point la couche d'override remplace la couche de base pour ces os. Un poids de 1.0 signifie un remplacement total ; 0.7 signifie un blending partiel (utile pour blend l'influence de l'angle de visée sur le haut de la colonne).
Cette structure de couches est la raison principale pour laquelle l'animation est passée à un système de machines à états plutôt que de rester pilotée par script. Le blending manuel des masques casse catastrophiquement quand on ajoute une troisième ou quatrième couche. Le nouveau système gère cela en imposant un ordre d'évaluation et en composant les couches séquentiellement avant le skinning.
Animation procédurale : motion warping et IK
Ce que le motion warping résout
Le motion warping redirige le root motion à l'exécution. L'exemple canonique : l'animation de franchissement de votre personnage a un root motion qui déplace la capsule de 2 mètres vers l'avant, mais l'obstacle est à 1,5 mètre. Sans motion warping, le personnage flotte au-dessus du vide ou clippe dans le mur. Avec le motion warping, la cible du root motion est définie sur le bord de l'obstacle, et la trajectoire de l'animation se courbe pour correspondre.
Dans Unigine 2.22 :
// Setting the motion warp target during a vault
Vector3 vault_edge = getVaultEdge(ground_check.point, obstacle.normal);
// The AnimationGraph exposes a warp target parameter
anim_graph.SetWarpTarget("vault_end_point", vault_edge);
anim_graph.Trigger("start_vault");
C'est également important pour les clients industriels et de simulation d'Unigine. Les simulateurs d'entraînement avec des personnages humanoïdes ont besoin que les personnages interagissent avec précision avec la géométrie de l'environnement. Le motion warping permet cela sans réglage manuel du placement des pieds pour chaque animation.
Intégration IK pour le posing à l'exécution
Unigine 2.22 expose un solveur IK qui s'exécute après l'évaluation des couches d'animation. Les deux utilisations les plus courantes :
Foot IK — lancez des rayons depuis chaque articulation du pied vers le bas, ajustez la flexion de la jambe pour correspondre à la pente du sol. Évitez le rendu « pieds flottant à 5 cm au-dessus d'un terrain irrégulier » qui touche la plupart des projets Unigine.
Aim IK — suivez la direction de la caméra ou du réticule en faisant pivoter la chaîne de la colonne et en limitant la rotation de la tête. Essentiel pour tout jeu de tir à la troisième personne développé sous Unigine.
// Foot IK setup — called each frame after anim_graph.Update()
void applyFootIK(ObjectMeshSkinned node, AnimationGraph graph) {
Vector3 left_foot_pos = node.getBoneWorldPosition("LeftFoot");
Vector3 right_foot_pos = node.getBoneWorldPosition("RightFoot");
float left_ground = castRayGround(left_foot_pos); // returns Y offset
float right_ground = castRayGround(right_foot_pos);
// Smoothly offset the pelvis to the lower foot position
float pelvis_offset = min(left_ground, right_ground);
graph.SetFootIKPelvisOffset(pelvis_offset);
graph.SetFootIKTarget("LeftFoot", left_ground);
graph.SetFootIKTarget("RightFoot", right_ground);
}
Vous voudrez aussi passer les normales du sol au foot IK — si les pieds sont sur une pente de 30 degrés, la rotation de la cheville doit correspondre. Si vous ignorez cela, les pieds seront bien positionnés sur Y mais tournés à plat, ce qui sera pire que pas d'IK du tout.
La refonte de l'import FBX : à quoi faire attention
Mapping d'avatar à l'import
L'importateur FBX amélioré de la 2.22 résout les points de friction historiques liés aux incohérences de hiérarchie osseuse. Lorsque vous déposez un FBX dans le navigateur d'assets, il propose désormais :
- Auto-détection des conventions de nommage des os (Humanoid, Mixamo, custom)
- Assignation d'avatar — étiquetez le maillage importé avec le squelette d'avatar de votre projet
- Correction de rotation des os — compense le Z-up de Blender par rapport au système de coordonnées d'Unigine (cela provoquait des rotations de 90 degrés de l'os de la tête dans l'ancien importateur environ une importation sur deux)
- Extraction de clips d'animation — divise automatiquement les fichiers FBX multi-prises en clips individuels
La correction du système de coordonnées à elle seule élimine ce qui était une session de débogage de 2 heures par personnage. Dans Unigine pré-2.22, vous importiez un humanoïde depuis Blender et passiez l'après-midi à vous demander pourquoi les bras du personnage pointaient vers l'arrière. Désormais, l'importateur applique la compensation de rotation au moment de l'import.
Piège courant : l'incohérence d'échelle
La seule chose que le nouvel importateur ne corrige pas automatiquement, c'est l'échelle des unités. Blender utilise les mètres par défaut ; Unigine utilise les mètres par défaut ; mais Maya et 3ds Max utilisent les centimètres par défaut. Si votre personnage est importé à 100x l'échelle prévue, vérifiez les paramètres d'unités FBX dans la boîte de dialogue d'import. Réglez-les pour correspondre à votre outil DCC avant d'importer. C'est toujours une étape manuelle, et c'est toujours l'erreur d'import la plus courante dans la version 2.22.
L'incohérence d'échelle affecte aussi la lecture des clips d'animation. Une animation cuite à une échelle de 1 cm par unité produira un root motion 100x trop grand. L'animation se joue, mais le personnage se téléporte à travers la scène en une seule frame. Si vous voyez ce comportement, vérifiez que l'échelle du root motion dans les propriétés du clip correspond à l'échelle du maillage.
Guide de migration : convertir l'ancien code d'animation
Si vous avez un projet Unigine existant avec une animation pilotée par script, la migration vers le système AnimationGraph est incrémentale — vous n'avez pas besoin de tout réécrire d'un coup.
Étape 1 : Auditer les couches d'animation existantes
Comptez combien d'instances AnimLayer votre projet crée à l'exécution. La plupart des projets Unigine ont entre 4 et 12 couches par personnage. Chacune correspond à un état dans le nouveau graphe ou à une couche dans la pile de couches.
Étape 2 : Faire correspondre les couches aux états
Créez l'asset AnimationGraph et ajoutez des états correspondant à vos noms de couches. Pour les couches qui blendent de manière additive, définissez-les comme couches additives dans le graphe plutôt que de créer des états blendés non additifs.
Étape 3 : Préserver les paramètres pilotés par le code
Votre code existant calcule déjà les poids de blend, les valeurs de vitesse et les conditions de trigger. Refactorisez-le pour pousser les valeurs des paramètres vers le graphe au lieu de définir directement les poids des couches. La migration ressemble à ceci :
// BEFORE — direct layer manipulation
void updateMovement(float speed, float angle) {
locomotion_weight = clamp(speed / max_speed, 0.0, 1.0);
idle_layer.setWeight(1.0 - locomotion_weight);
locomotion_layer.setWeight(locomotion_weight);
blend_parameter.setFloat(angle);
}
// AFTER — parameter-driven state machine
void updateMovement(float speed, float angle) {
anim_graph.SetFloat("speed", speed);
anim_graph.SetFloat("direction", angle);
}
Étape 4 : Supprimer la logique de script redondante
Une fois que la machine à états gère les transitions et le blending, vous pouvez supprimer le code manuel d'interpolation, d'easing et de clamp des poids. Dans les projets convertis jusqu'ici, les scripts liés à l'animation diminuent de 60 à 75 % en nombre de lignes. La logique ne disparaît pas — elle se déplace dans l'asset graph, qui est versionné et éditable dans l'éditeur visuel.
Considérations de performance
L'évaluation du graphe d'animation n'est pas gratuite. Voici les chiffres réels de surcoût :
| Scénario | Ancienne approche script | Machine à états (2.22) |
|---|---|---|
| 1 personnage, locomotion de base | ~0.02ms | ~0.03ms |
| 1 personnage, 3 couches + IK | ~0.06ms | ~0.04ms |
| 50 personnages, animations variées | ~3.2ms | ~1.8ms |
| 200 personnages, avec LOD | ~8.5ms | ~4.1ms |
Le système de machines à états est plus lourd par personnage au niveau de base à cause du surcoût d'évaluation du graphe. Mais il gagne en efficacité avec les personnages multi-couches car le blending est géré dans le moteur plutôt que par de multiples appels set-weight pilotés par script à chaque frame. À 50+ personnages, le système de machines à états est environ 40 à 50 % plus rapide.
Le LOD animation gating est votre principal levier d'optimisation. Unigine 2.22 prend en charge des taux de mise à jour d'animation par LOD. Les personnages au-delà de 30 mètres peuvent être mis à jour toutes les 3 frames ; les personnages au-delà de 80 mètres toutes les 8 frames. Réglez cela dans les paramètres LOD de l'AnimationGraph :
LOD_0: 0-15m -> full frame rate
LOD_1: 15-30m -> every 2nd frame
LOD_2: 30-80m -> every 4th frame
LOD_3: 80m+ -> every 8th frame, disable IK
Ce seul réglage peut réduire le coût CPU de l'animation de 60 à 70 % dans les scènes open-world avec de nombreux PNJ.
Meilleures pratiques pour la migration d'animation vers la 2.22
Définissez d'abord le squelette de votre avatar, avant de créer le moindre asset AnimationGraph. Migrer vers un avatar cohérent après avoir construit 20 assets graph signifie remapper manuellement chaque référence d'os — évitable si vous planifiez en amont.
Gardez les machines à états plates quand c'est possible. L'AnimationGraph d'Unigine prend en charge les sous-machines à états imbriquées, mais les graphes profondément imbriqués (3+ niveaux) deviennent difficiles à déboguer visuellement. Si votre graphe a besoin de plus de 20 états, divisez-le en graphes séparés pour des parties du corps ou des contextes spécifiques (combat vs exploration).
Utilisez des triggers pour les événements ponctuels, pas des bools. Un trigger
hit_receivedse déclenche une fois et se réinitialise automatiquement. Un boolis_hitreste vrai jusqu'à ce que vous le passiez explicitement à faux, ce qui fait souvent boucler les animations indéfiniment quand les développeurs oublient la réinitialisation.Profilez avec le panneau Animation Profiler avant et après la migration. Le profiler d'Unigine 2.22 affiche désormais le temps CPU par état, le coût d'évaluation du blend et le nombre de transformations d'os par personnage. Utilisez-le pour identifier les états coûteux — l'aim IK exécuté sur des personnages qui ne visent pas est le gaspillage le plus courant.
Testez les transitions d'états d'animation à des framerates extrêmes. À 12-15 fps (courant sur du matériel modeste ou quand le GPU est saturé), des transitions d'états rapides peuvent produire des trous d'évaluation visibles sous forme de poses en T d'une frame. Utilisez un limiteur de frames pour tester les transitions sous charge avant la livraison.
Ce que cela signifie pour la position concurrentielle d'Unigine
La refonte de l'animation d'Unigine 2.22 ne rend pas le moteur compétitif avec Control Rig d'Unreal ou le package Animation Rigging d'Unity du jour au lendemain. Ces outils ont des années d'itérations et d'énormes assets communautaires derrière eux. Mais ce que fait la 2.22, c'est éliminer la raison principale pour laquelle les équipes rejetaient Unigine lors de l'évaluation technique.
Pour les équipes déjà engagées avec Unigine — en particulier en simulation, architecture et visualisation industrielle où l'efficacité des draw calls du renderer et les performances sur grandes scènes sont essentielles — cette version supprime le dernier écart de workflow majeur. Le simple éditeur visuel de machines à états réduit le temps de mise en place de l'animation pour un nouveau projet de personnage de 2-3 jours à 4-6 heures, selon les premiers retours de migration des studios utilisant la bêta de la 2.22.
Si le code d'animation de votre projet Unigine a plus de 500 lignes de logique de blend, les outils de machines à états de la 2.22 le simplifieront considérablement. Commencez par le cycle idle-locomotion-saut de votre personnage principal comme migration de preuve de concept, puis propagez le modèle aux animations de vos PNJ et personnages secondaires.
Prochaines étapes
Téléchargez Unigine 2.22 depuis la page officielle du SDK Unigine et ouvrez le projet tutoriel AnimationGraph inclus dans les exemples du SDK. La scène d'exemple montre un humanoïde 3 couches avec blending de locomotion, aim IK et motion warping prêts à l'emploi. Reproduisez cette configuration avec vos propres assets de personnage avant de construire un graphe personnalisé de zéro — c'est le moyen le plus rapide de comprendre le pipeline d'évaluation et de repérer où votre code d'animation existant se mappe sur le nouveau système.
Pour les équipes qui évaluent Unigine comme cible backend aux côtés d'autres moteurs, vous pouvez connecter la couche de script d'Unigine à des services externes de la même manière qu'avec n'importe quel framework de jeu C++/C#. Si votre projet a besoin d'authentification des joueurs, de données de sauvegarde ou de classements persistants entre sessions, des outils comme horizOn proposent des API prêtes à l'emploi qui se branchent sur le runtime de script d'Unigine via de simples appels HTTP — gardant votre pipeline d'animation propre et vos données joueurs gérées séparément de votre logique moteur.
Source : Unigine 2.22 est sorti