Controlling game character animation in Godot 4 requires more than `AnimationPlayer` — the moment you need blended locomotion, directional movement, or state-driven transitions, you need `AnimationTree`. This guide walks through the complete setup: building a `StateMachine`, configuring `BlendSpace2D` for directional movement, setting transition conditions via GDScript, and importing GLB animations cleanly from Blender.
AnimationTree vs AnimationPlayer: which to use
`AnimationPlayer` plays individual animation clips. It handles simple cases well — a door opening, a platform moving, a UI fade. But for a character with idle, walk, run, jump, and attack states that blend together based on velocity and input, `AnimationPlayer` alone becomes unmanageable.
`AnimationTree` is a node that sits on top of `AnimationPlayer` and routes playback through a graph of logic nodes:
- StateMachine — drives transitions between named states via conditions
- BlendSpace1D / BlendSpace2D — interpolates between animations based on one or two float inputs
- BlendTree — mixes animations with adjustable weights
- Transition — simple crossfade between two clips
![]()
You can combine these: a `StateMachine` at the root with each state containing a `BlendSpace2D` for locomotion, a separate state for jumping, and a transition to an attack state. The hierarchy mirrors how a real character animation system works.
Setup basics:
```gdscript
@onready var anim_tree: AnimationTree = $AnimationTree
@onready var anim_player: AnimationPlayer = $AnimationPlayer
func _ready() -> void:
anim_tree.active = true
anim_tree["parameters/StateMachine/current_node"] = "Idle"
```
Set `AnimationTree.anim_player` in the inspector to point at your `AnimationPlayer`. Enable `active` either in the inspector or via code.
Setting up a StateMachine in Godot 4
In the `AnimationTree` panel (bottom editor area), double-click the node to open the graph view. Add a `StateMachine` node as the root (right-click → Add Node → StateMachine).
Inside the `StateMachine`:
1. Add states by right-clicking → Add Node → Animation and naming each one (`Idle`, `Walk`, `Run`, `Jump`, `Attack`)
2. Connect states with transition arrows (hover a state, then drag from the arrow that appears)
3. Set the Start node to your initial state
Each transition has:
- Switch Mode: `Immediate` (cuts instantly), `Sync` (waits for sync point), `At End` (waits for clip end)
- Auto Advance: triggers the transition when its condition becomes true
- Conditions: boolean or float comparisons you drive from code
To add a condition:
```gdscript
func _physics_process(delta: float) -> void:
var velocity := CharacterBody3D(owner).velocity
var speed := velocity.length()
anim_tree["parameters/StateMachine/conditions/is_moving"] = speed > 0.1
anim_tree["parameters/StateMachine/conditions/is_jumping"] = not CharacterBody3D(owner).is_on_floor()
```
In the `StateMachine` editor, on the transition from Idle → Walk, enable Auto Advance and set Condition to `is_moving`. The transition fires automatically once the condition is true.
BlendSpace2D for directional movement
`BlendSpace2D` maps two float inputs — typically horizontal and vertical velocity — to a 2D grid of animation clips. Godot interpolates between the nearest clips based on the current parameter values.
Inside the locomotion state, replace the `Animation` node with a `BlendSpace2D`:
1. Open the `BlendSpace2D` editor
2. Set X Axis label to `velocity_x`, range `-1` to `1`
3. Set Y Axis label to `velocity_z`, range `-1` to `1`
4. Add animation points at the corners and center:
- `(0, 0)` → Idle
- `(0, 1)` → Walk Forward
- `(0, -1)` → Walk Backward
- `(-1, 0)` → Strafe Left
- `(1, 0)` → Strafe Right
Godot triangulates the grid automatically. Drive the blend position from code:
```gdscript
func _physics_process(delta: float) -> void:
var local_vel := owner.global_transform.basis.inverse() * CharacterBody3D(owner).velocity
var blend_pos := Vector2(local_vel.x, local_vel.z).limit_length(1.0)
anim_tree["parameters/StateMachine/locomotion/BlendSpace2D/blend_position"] = blend_pos
```
Use `local_vel` (velocity in local space) so strafing maps to the correct animation axis regardless of character rotation.
![]()
Blend modes: The default `Interpolated` mode trilinearly blends between the three nearest points. `Discrete` switches abruptly to the nearest point — useful for 8-directional movement without foot-sliding artefacts. `Carry` interpolates but remembers the last blend position, reducing jitter when the character stops.
Importing GLB animations and connecting to AnimationTree
When exporting from Blender for Godot 4, use these GLB settings:
```
Format: glTF 2.0 (.glb)
Include → Animations: ✓
NLA Tracks: Push Down Actions Before Export
Rest & Ranges → Always Export Bones: ✓
Armature → Add Leaf Bones: ✗ (Godot adds its own)
```
On import into Godot 4:
1. Select the `.glb` in the FileSystem panel
2. Open Import tab → Animation → set `Import` to `All Clips`
3. Under Animation → Clips, rename animations to match your state names (`Idle`, `Walk_Forward`, `Run`)
4. Hit Reimport
The imported animations live inside the `.glb` resource. Reference them in `AnimationPlayer` by their clip name. Name your Blender NLA strips exactly what you want the Godot clip to be called — Godot preserves the strip name on import.
Set Loop Mode per clip in the Import tab:
| Clip type | Loop Mode |
|---|---|
| Idle, Walk, Run | Loop |
| Jump, Land, Attack | No Loop |
| Death | No Loop |
| Hit reaction | No Loop |
Clips with wrong loop settings cause the `StateMachine` to hold or cut unexpectedly at `At End` transitions.
Pre-wiring checklist
- [ ] Armature scale is 1.0, 1.0, 1.0 in Godot scene (apply scale in Blender before export)
- [ ] No `.001` bone name suffixes (check Blender outliner for duplicates)
- [ ] Clip count matches your Blender NLA strip count
- [ ] Loop flags set correctly per clip type
- [ ] `AnimationTree.anim_player` points at the correct `AnimationPlayer` node
- [ ] `AnimationTree.active` is `true` at runtime
Practical tips
- Nested StateMachines: build a top-level machine (Ground / Air / Ragdoll) with sub-machines for each state group. Keeps the graph readable as complexity grows.
- TimeScale parameter: use `parameters/StateMachine/attack/TimeScale/scale` to speed up a single clip without duplicating it.
- One-shot animations: use a `OneShot` node inside a `BlendTree` for hit reactions — it overlays for the clip duration then returns to the base state automatically.
- Root motion: enable `Root Motion Track` in `AnimationTree` and read `anim_tree.get_root_motion_position()` each physics frame to drive movement from animation data rather than from code velocity.
For production Godot 4 projects, browse free rigged characters and animated props at the BitSoul 3D marketplace — all GLB assets include clean bone hierarchies ready to wire into `AnimationTree` without rework.
---
*This post is part of the Ultimate Guide to Free 3D Game Assets — BitSoul's complete reference for formats, texturing, rigging, optimization, and engine integration.*