Unigine 2.22 Animation-Overhaul: State Machines, Layer Blending und der neue Skeletal-Workflow
Kurz und knapp
Entdecken Sie das vollständige Animation-Overhaul von Unigine 2.22: State Machines, Layer Blending und der neue Skeletal-Workflow im Überblick.
Der Animations-Workflow, der Unigine-Entwickler die Engine verlassen ließ
Jeder Unigine-Entwickler ist schon gegen dieselbe Wand gelaufen: Der Renderer liefert atemberaubende PBR-Szenen mit 120fps, aber einen einfachen Idle-to-Run-Blend zu erstellen dauert eine Stunde voller Scripting-Hacks und manueller Bone-Anpassungen. Diese Diskrepanz zwischen visueller Wiedergabetreue und Animationstools ist seit Jahren Unigines offenes Geheimnis – und der Grund, warum die meisten kleinen Teams, die Unigine evaluieren, letztendlich wieder gehen.
Mit Unigine 2.22 hat das Team diese Lücke endlich direkt angegangen. Das Release führt einen visuellen Animation-State-Machine-Editor, additives Layer Blending mit Per-Bone-Masks, eine verbesserte FBX-Import-Pipeline mit Avatar-Skeleton-Mapping und eine neue prozedurale Motion-Warping-API ein. Für Teams, die Unigine für Simulation, architektonische Visualisierung oder industrielle Anwendungen nutzen und seit Jahren Animationslogik mühsam im Code zusammenstricken, ändert das den Arbeitsalltag erheblich.
Dieser Guide zeigt, was sich tatsächlich geändert hat, wie man vom alten script-lastigen Ansatz zu den neuen State-Machine-Tools migriert – und wo die Edge Cases am härtesten zubeißen.
Was sich im Animationssystem von Unigine 2.22 geändert hat
Der alte Weg: Script-getriebene Animationslogik
Vor 2.22 bedeutete das Auslösen eines Animationsübergangs in Unigine, die Logik selbst zu schreiben:
// 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);
}
}
Das funktioniert für ein Zwei-State-System, aber es auf Crouch, Jump, Aim, Sprint und 15 Angriffsvarianten zu skalieren, wird schnell unwartbar. Jedes Team endet mit einer selbstgebauten State Machine im Script und kämpft anschließend mit Übergangs-Pops und Blending-Glitches.
Der 2.22-Ansatz: Deklarative State Machines
Unigine 2.22 führt das AnimationGraph-System ein – einen node-basierten State-Machine-Editor, der in den Unigine Editor integriert ist, zusammen mit einer Scripting-API zur Laufzeitsteuerung. States werden auf Animationsclips oder Blend Spaces abgebildet. Transitions definieren Bedingungen und Dauern. Die Engine übernimmt Interpolation, Interrupt-Blending und Layer-Komposition intern.
Die wichtigsten Verbesserungen:
- Visueller State-Machine-Editor – States, Transitions und Bedingungen im Editor mit einer Graph-Vorschau definieren
- Layer-Stacking mit Bone-Masks – Oberkörper-Aim über Unterkörper-Locomotion mit benannten Bone-Gruppen blenden
- Additive-Animation-Support – Lean, Head Look und Recoil als Offsets anwenden statt als vollständige Pose-Ersetzungen
- Verbesserter FBX-Import – Avatar-Skeleton-Mapping, das Bone-Hierarchien über Charaktervarianten hinweg erhält
- Motion Warping – Root Motion kann zur Laufzeit für Klettern, Vaulting und Cover-Transitions umgeleitet und geblendet werden
Die neue Animations-Pipeline Schritt für Schritt einrichten
Schritt 1: Avatar-Skeleton definieren
Das Avatar-Skeleton ist das Herzstück des 2.22-Workflows. Es ist eine benannte Bone-Vorlage, die Skeletal Meshes aus DCC-Tools (Blender, Maya, 3ds Max) auf ein kanonisches Skeleton abbildet, auf das die Animation State Machine referenziert.
Wenn man diesen Schritt überspringt – und viele Entwickler, die das System lernen, tun das –, spielen Animationen auf den falschen Bones oder gar nicht. Die Engine wirft keinen Fehler; sie verwendet stillschweigend den ersten Bone mit passendem Namen, was bizarre Rendering-Artefakte verursacht.
Im Skeleton-Asset-Panel des Editors definierst du dein 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";
}
}
Jedes Charakter-Asset in deinem Projekt teilt sich diese Avatar-Definition. Wenn du einen neuen Humanoiden importierst, ordnest du seine Bone-Namen einmal den Avatar-Namen zu, und jeder Animationsclip von jedem Charakter funktioniert mit den Animationen aller anderen Charaktere. Die typische Einrichtungszeit für dieses Mapping beträgt 10-15 Minuten pro Charakter – im Vergleich zum alten Ansatz, Anchor-Points pro Animationsclip manuell zu benennen, was 30-60 Minuten pro Charakter dauerte und bei jedem Retargeting brach.
Schritt 2: Die State Machine im Editor bauen
Öffne den AnimationGraph-Editor aus dem Asset-Browser von Unigine 2.22. Für einen grundlegenden Character Controller brauchst du mindestens:
- Idle-State – loopende Idle-Animation, Entry-State
- Locomotion-Blend-Space – 2D-Blend aus Walk/Jog/Run basierend auf Geschwindigkeits- und Richtungsparametern
- Jump-State – nicht-loopender Jump-Start und Airborne-Transitions
- Land-State – gestaffelte Erholung mit unterbrechbarer Transition zurück zur Locomotion
Jeder State referenziert einen Animationsclip oder Blend Space. Transitions verbinden States über Condition-Parameter – Floats, Bools oder Trigger, die du zur Laufzeit aus dem Code setzt.
[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]
Schritt 3: Per Code ansteuern
Die Scripting-Seite ist drastisch vereinfacht. Statt Blend-Gewichte manuell zu berechnen, schiebst du pro Frame Parameterwerte:
// 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;
}
Die alte Version dieses Codes umfasste 120-180 Zeilen manuelles Blend-Management. Die neue Version hat unter 30 Zeilen, weil State Machine, Blending und Transition-Logik im Graph-Asset leben.
Schritt 4: Layer Blending für Ober-/Unterkörper konfigurieren
Für einen Charakter, der beim Rennen zielen muss, brauchst du zwei Animations-Layer, die mit Bone-Masks geblendet werden. Im 2.22-AnimationGraph-Editor:
Layer 0 (Basis): Locomotion-State-Machine – betrifft Hüfte, Beine, Rumpfwirbelsäule Layer 1 (Oberkörper-Override): Aim-Blend-Space – betrifft Wirbelsäule, Arme, Kopf Layer 2 (additiv): Recoil-Animation – additiver Offset auf rechtem Arm und Wirbelsäule
Die Bone-Masks verwenden die Avatar-Bone-Gruppen aus Schritt 1. Das Mask-Blend-Gewicht definiert, wie stark der Override-Layer den Basis-Layer für diese Bones ersetzt. Ein Gewicht von 1.0 bedeutet vollständige Ersetzung; 0.7 bedeutet teilweises Blending (nützlich, um den Einfluss des Aim-Winkels auf die obere Wirbelsäule zu blenden).
Diese Layer-Struktur ist der Hauptgrund, warum Animation auf ein State-Machine-System umgestellt wurde, statt script-getrieben zu bleiben. Manuelles Mask-Blending bricht katastrophal, sobald ein dritter oder vierter Layer hinzukommt. Das neue System löst das, indem es eine Auswertungsreihenfolge erzwingt und die Layer vor dem Skinning sequenziell composited.
Prozedurale Animation: Motion Warping und IK
Was Motion Warping löst
Motion Warping leitet Root Motion zur Laufzeit um. Das klassische Beispiel: Deine Vault-Animation hat Root Motion, die die Kapsel 2 Meter nach vorne bewegt, aber das Hindernis ist 1,5 Meter entfernt. Ohne Motion Warping schwebt der Charakter entweder über die Lücke oder kollidiert mit der Wand. Mit Motion Warping wird das Root-Motion-Ziel auf die Hinderniskante gesetzt und die Animations-Trajektorie biegt sich entsprechend.
In 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");
Das ist auch für Unigines Industrie- und Simulationskunden bedeutsam. Trainingssimulatoren mit humanoiden Charakteren benötigen eine präzise Interaktion mit der Umgebungsgeometrie. Motion Warping liefert das, ohne dass die Fußposition pro Animation von Hand nachjustiert werden muss.
IK-Integration für Runtime-Posing
Unigine 2.22 bietet einen IK-Solver, der nach der Animations-Layer-Auswertung läuft. Die zwei häufigsten Anwendungen:
Foot-IK – Rays von jedem Fußgelenk nach unten werfen und die Beinbeugung an das Bodengefälle anpassen. Verhindert den Look von „Füßen, die 5 cm über unebenem Gelände schweben“, der die meisten Unigine-Projekte plagt.
Aim-IK – Kamera- oder Fadenkreuzrichtung verfolgen, indem die Wirbelsäulenkette rotiert und die Kopfbewegung begrenzt wird. Essenziell für jeden Third-Person-Shooter, der in Unigine gebaut wird.
// 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);
}
Du solltest auch Ground-Normal-Daten in das Foot-IK übergeben – wenn die Füße auf einem 30-Grad-Hang stehen, muss die Knöchelrotation mitmachen. Wenn du das weglässt, werden die Füße zwar auf Y korrekt positioniert, aber flach rotiert – das sieht schlimmer aus als gar kein IK.
Die FBX-Import-Überarbeitung: Worauf du achten musst
Avatar-Mapping beim Import
Der verbesserte FBX-Importer in 2.22 löst historische Schmerzpunkte bei Bone-Hierarchie-Inkompatibilitäten. Wenn du ein FBX in den Asset-Browser ziehst, bietet er jetzt:
- Auto-Erkennung von Bone-Namenskonventionen (Humanoid, Mixamo, Custom)
- Avatar-Zuweisung – das importierte Mesh mit dem Avatar-Skeleton deines Projekts taggen
- Bone-Rotations-Fix – kompensiert Blenders Z-up gegenüber Unigines Koordinatensystem (das verursachte im alten Importer bei etwa jedem zweiten Import 90-Grad-Rotationen am Head-Bone)
- Animationsclip-Extraktion – teilt Multi-Take-FBX-Dateien automatisch in einzelne Clips
Allein der Koordinatensystem-Fix eliminiert, was früher eine 2-stündige Debugging-Sitzung pro Charakter war. In Unigine vor 2.22 hast du einen Blender-Humanoiden importiert und den Nachmittag damit verbracht, dich zu fragen, warum die Arme des Charakters nach hinten zeigen. Jetzt wendet der Importer die Rotationskompensation bereits beim Import an.
Häufige Falle: Scale-Mismatch
Das Einzige, was der neue Importer nicht automatisch korrigiert, ist der Einheitenmaßstab. Blender verwendet standardmäßig Meter; Unigine verwendet Meter; aber Maya und 3ds Max verwenden Zentimeter. Wenn dein Charakter mit dem 100-fachen Maßstab importiert wird, prüfe die FBX-Einheitseinstellungen im Import-Dialog. Stelle sie vor dem Import auf dein DCC-Tool ein. Das ist weiterhin ein manueller Schritt – und weiterhin der häufigste Importfehler im 2.22-Release.
Scale-Mismatch betrifft auch die Wiedergabe von Animationsclips. Eine Animation, die mit 1-cm-pro-Einheit-Maßstab gebacken wurde, erzeugt Root Motion, die 100x zu groß ist. Die Animation spielt, aber der Charakter teleportiert in einem einzigen Frame durch die Szene. Wenn du dieses Verhalten siehst, prüfe, ob die Root-Motion-Skalierung in den Clip-Eigenschaften mit dem Mesh-Maßstab übereinstimmt.
Migrationsleitfaden: Alten Animationscode konvertieren
Wenn du ein bestehendes Unigine-Projekt mit script-getriebener Animation hast, ist die Migration zum AnimationGraph-System inkrementell – du musst nicht alles auf einmal neu schreiben.
Schritt 1: Vorhandene Animations-Layer prüfen
Zähle, wie viele AnimLayer-Instanzen dein Projekt zur Laufzeit erstellt. Die meisten Unigine-Projekte haben zwischen 4 und 12 Layern pro Charakter. Jeder davon wird zu einem State im neuen Graph oder einem Layer im Layer-Stack.
Schritt 2: Layer auf States abbilden
Erstelle das AnimationGraph-Asset und füge States hinzu, die deinen Layer-Namen entsprechen. Für Layer, die additiv blenden, setze sie als additive Layer im Graph, statt nicht-additive Blend-States zu erzeugen.
Schritt 3: Code-getriebene Parameter beibehalten
Dein bestehender Code berechnet bereits Blend-Gewichte, Geschwindigkeitswerte und Trigger-Bedingungen. Refaktoriere das so, dass Parameterwerte an den Graph übergeben werden, statt direkt Layer-Gewichte zu setzen. Die Migration sieht so aus:
// 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);
}
Schritt 4: Redundante Script-Logik entfernen
Sobald die State Machine Transitions und Blending übernimmt, kannst du den manuellen Interpolations-, Easing- und Weight-Clamping-Code löschen. In bisher konvertierten Projekten schrumpfen animationsbezogene Scripts um 60-75 % der Zeilenanzahl. Die Logik verschwindet nicht – sie wandert ins Graph-Asset, das versioniert und im visuellen Editor bearbeitbar ist.
Performance-Überlegungen
Die Auswertung des Animation-Graphs ist nicht gratis. Hier sind die tatsächlichen Overhead-Zahlen:
| Szenario | Alter Script-Ansatz | State Machine (2.22) |
|---|---|---|
| 1 Charakter, grundlegende Locomotion | ~0.02ms | ~0.03ms |
| 1 Charakter, 3 Layer + IK | ~0.06ms | ~0.04ms |
| 50 Charaktere, gemischte Animationen | ~3.2ms | ~1.8ms |
| 200 Charaktere, LOD-gegatet | ~8.5ms | ~4.1ms |
Das State-Machine-System ist auf Basisebene pro Charakter schwerer, weil der Graph-Auswertungs-Overhead anfällt. Aber es wird bei Charakteren mit Layern effizienter, weil das Blending in der Engine erledigt wird, statt durch mehrere script-getriebene Set-Weight-Aufrufe pro Frame. Ab 50+ Charakteren ist das State-Machine-System etwa 40-50 % schneller.
LOD-Animation-Gating ist dein wichtigster Optimierungshebel. Unigine 2.22 unterstützt pro-LOD-Update-Raten für Animationen. Charaktere jenseits von 30 Metern können jeden 3. Frame aktualisiert werden; Charaktere jenseits von 80 Metern jeden 8. Frame. Das stellst du in den LOD-Einstellungen des AnimationGraph ein:
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
Das allein kann die CPU-Kosten für Animationen in Open-World-Szenen mit vielen NPCs um 60-70 % senken.
Best Practices für die 2.22-Animationsmigration
Definiere zuerst dein Avatar-Skeleton, bevor du AnimationGraph-Assets erstellst. Nach dem Bau von 20 Graph-Assets auf ein konsistentes Avatar zu migrieren bedeutet, jede Bone-Referenz manuell neu zu mappen – vermeidbar, wenn du vorausplanst.
Halte State Machines wann immer möglich flach. Unigines AnimationGraph unterstützt verschachtelte Sub-State-Machines, aber tief verschachtelte Graphen (3+ Ebenen) sind visuell schwer zu debuggen. Wenn dein Graph mehr als 20 States braucht, teile ihn in separate Graphen für bestimmte Körperteile oder Kontexte (Kampf vs. Erkundung).
Nutze Trigger für Einmal-Ereignisse, keine Bools. Ein
hit_received-Trigger feuert einmal und setzt sich automatisch zurück. Einis_hit-Bool bleibt true, bis du ihn explizit auf false setzt, was häufig dazu führt, dass Animationen endlos loopen, wenn Entwickler das Zurücksetzen vergessen.Erstelle vor und nach der Migration ein Profil mit dem Animation-Profiler-Panel. Der Profiler von Unigine 2.22 zeigt jetzt CPU-Zeit pro State, Blend-Auswertungskosten und Bone-Transform-Zählungen pro Charakter. Nutze ihn, um teure States zu identifizieren – Aim-IK auf Charakteren, die gar nicht zielen, ist die häufigste Verschwendung.
Teste Animations-State-Transitions bei extremen Framerates. Bei 12-15fps (häufig bei schwacher Hardware oder gesättigter GPU) können schnelle State-Transitions Auswertungslücken erzeugen, die als einzelne T-Pose-Frames sichtbar werden. Nutze einen Frame-Limiter, um Transitions unter Last zu testen, bevor du auslieferst.
Was das für Unigines Wettbewerbsposition bedeutet
Die Animations-Überarbeitung von Unigine 2.22 macht die Engine nicht über Nacht konkurrenzfähig mit Unreals Control Rig oder Unities Animation Rigging Package. Diese Tools haben Jahre der Iteration und riesige Community-Assets hinter sich. Aber 2.22 beseitigt den Hauptgrund, warum Teams Unigine während der technischen Evaluierung abgelehnt haben.
Für Teams, die sich bereits für Unigine entschieden haben – vor allem in Simulation, Architektur und industrieller Visualisierung, wo die Draw-Call-Effizienz des Renderers und die Large-Scene-Performance entscheidend sind – beseitigt dieses Release die letzte große Workflow-Lücke. Allein der visuelle State-Machine-Editor reduziert die Animations-Einrichtungszeit für ein neues Charakterprojekt von 2-3 Tagen auf 4-6 Stunden, so frühe Migrationsberichte von Studios, die die 2.22-Beta nutzen.
Wenn der Animationscode deines Unigine-Projekts mehr als 500 Zeilen Blend-Logik enthält, werden die 2.22-State-Machine-Tools ihn erheblich vereinfachen. Beginne mit dem Idle-Locomotion-Jump-Zyklus deiner Hauptfigur als Proof-of-Concept-Migration und übertrage das Muster dann auf deine NPC- und Nebenfiguren-Animationen.
Nächste Schritte
Lade Unigine 2.22 von der offiziellen Unigine-SDK-Seite herunter und öffne das AnimationGraph-Tutorialprojekt in den SDK-Beispielen. Die Beispielszene zeigt sofort einen 3-Layer-Humanoiden mit Locomotion-Blending, Aim-IK und Motion Warping. Repliziere dieses Setup mit deinen eigenen Charakter-Assets, bevor du einen eigenen Graph von Grund auf baust – das ist der schnellste Weg, die Auswertungs-Pipeline zu verstehen und zu erkennen, wo dein bestehender Animationscode in das neue System passt.
Für Teams, die Unigine neben anderen Engines als Backend-Ziel evaluieren: Du kannst die Scripting-Schicht von Unigine genauso an externe Dienste anbinden, wie du es bei jedem C++/C#-Game-Framework tun würdest. Wenn dein Projekt Spieler-Authentifizierung, gespeicherte Spielstände oder Leaderboards benötigt, die über Sitzungen hinweg bestehen, bieten Tools wie horizOn fertige APIs, die über einfache HTTP-Aufrufe in die Scripting-Runtime von Unigine integriert werden – so bleibt deine Animations-Pipeline sauber und deine Spielerdaten werden getrennt von der Engine-Logik verwaltet.
Quelle: Unigine 2.22 veröffentlicht