Animation
Build animation state machines with blending, transitions, and events.
Introduction
Animation brings characters to life. This guide covers state machines, blend trees, transition conditions, and animation events for responsive character animation.
Guide 8 of 25
Screenshot
Step-by-Step Guide
Import animations
Load FBX files with animation data. Each file becomes a clip (idle, walk, run, jump, attack).
Create a state machine
In the Animator component, create states for each clip. Set idle as the default entry point.
Add transitions
Connect states with conditions (speed > 0.1 to walk, speed > 5 to run, !isGrounded to jump).
Configure blend times
0.1-0.2s for responsive actions (jump, attack), 0.3-0.5s for relaxed transitions (idle to walk).
Use blend trees
For directional movement, create a blend tree parameterized by speed and angle for smooth blending.
Add animation events
Attach events at specific frames (frame 15 of attack = deal damage). Events trigger FluxScript functions.
FluxScript Example
Here is a complete FluxScript implementation for this guide:
on start {
player = scene.find("Player")
player.loadAnimation("idle", "anims/idle.fbx")
player.loadAnimation("walk", "anims/walk.fbx")
player.loadAnimation("run", "anims/run.fbx")
player.loadAnimation("jump", "anims/jump.fbx")
player.loadAnimation("attack", "anims/attack.fbx")
player.setStateMachine({
default: "idle",
transitions: [
{ from: "idle", to: "walk", when: "speed > 0.5", blend: 0.2 },
{ from: "walk", to: "run", when: "speed > 5", blend: 0.15 },
{ from: "*", to: "jump", when: "!isGrounded", blend: 0.05 },
{ from: "*", to: "attack", when: "attacking", blend: 0.1 }
]
})
}
on update(dt) {
player.setAnimParam("speed", player.getSpeed())
player.setAnimParam("isGrounded", player.isGrounded)
}
on animEvent("attack", "hit") {
enemies = world.findAll("enemy")
for i = 0 to enemies.length {
if math.distance(player.position, enemies[i].position) < 3 {
enemies[i].takeDamage(25)
}
}
}Node Graph Example
Prefer visual programming? Here is the equivalent Node Graph:
[On Start] --> [Load 5 Animation Clips]
--> [Set State Machine: 4 transitions]
[On Update] --> [Set Anim Params: speed, isGrounded]
[On Anim Event "attack" "hit"] --> [Find All: enemy]
--> [For Each: distance < 3] --> [Take Damage: 25]Optimization Tips
Keep your implementation fast and efficient with these optimization tips:
- Compress animation data to reduce file size and memory. Use keyframe reduction on idle and walk loops.
- Use additive blending for upper-body animations. This lets characters attack while walking.
- Limit concurrent animated characters. Each skeleton costs CPU. Use simpler rigs for background NPCs.
- Use animation events instead of polling. Trigger damage/sound at exact frames — polling is less precise.
Common Mistakes
Transitions too slow
Combat animations need 0.05-0.1s blends. Slower transitions make controls feel sluggish.
Missing animation events
Without events, damage applies during the entire attack. Use events for exact-frame damage.
