Skills/godot-animation/SKILL.md

303 lines
9.1 KiB
Markdown

---
name: godot-animation
description: "Animation systems for Godot 4.x: AnimationPlayer vs AnimationTree, state machines, blend spaces (1D/2D/directional), animation libraries, root motion, collapsible tracks, and tween_await(). Use when building character animations, cutscenes, or visual effects in Godot."
license: MIT
compatibility:
- godot-4.0
- godot-4.1
- godot-4.2
- godot-4.3
- godot-4.4
- godot-4.5
- godot-4.6
- godot-4.7
metadata:
author: vl4dt
version: 0.1.0
tags:
- godot
- animation
- animationplayer
- animationtree
- blend-space
- root-motion
created: 2026-06-20
---
# Animation Systems for Godot 4.x
Comprehensive patterns for character animation, state machines, and visual effects in Godot 4.x.
## AnimationPlayer vs AnimationTree
### AnimationPlayer — Simple Animations
Use AnimationPlayer for linear sequences, cutscenes, and simple property animations.
```gdscript
@onready var anim_player = $AnimationPlayer
func play_attack():
anim_player.play("attack")
func play_transition(target: String, fade_time: float = 0.2):
anim_player.play(target, fade_time)
# Signal-based animation completion
func _ready():
anim_player.animation_finished.connect(_on_animation_finished)
func _on_animation_finished(anim_name: String):
if anim_name == "attack":
print("Attack animation complete")
```
### AnimationTree — State Machine Animations
Use AnimationTree for complex character animations with branching states (idle, walk, run, jump).
```gdscript
@onready var anim_tree = $AnimationTree
@onready var anim_state = anim_tree.get("state_machine")
func _ready():
anim_state.travel("Idle") # Start at Idle state
func set_animation(state_name: String):
if anim_state.has_state(state_name):
anim_state.travel(state_name)
func _physics_process(delta: float):
var speed = velocity.length()
anim_tree.set("parameters/Move/speed", speed)
anim_tree.process(delta)
```
### When to Use Which
| Use Case | Tool |
|----------|------|
| Cutscenes, UI animations | AnimationPlayer |
| Character movement states | AnimationTree + StateMachine |
| Simple one-shot effects | AnimationPlayer |
| Blending between movements | AnimationTree + BlendSpace2D |
| Complex combat combos | AnimationTree + AnimationNodeBlendTree |
## State Machines in AnimationTree
### Building a Character State Machine
```gdscript
# In the AnimationTree, create an AnimationNodeStateMachine:
# States: Idle, Walk, Run, Jump, Fall, Attack
# Transitions: Idle <-> Walk, Idle <-> Run, Walk -> Run, etc.
@onready var anim_tree = $AnimationTree
@onready var state_machine = anim_tree.get("state_machine")
func _physics_process(delta: float):
var speed = velocity.length()
var new_state = "Idle"
if not is_on_floor():
new_state = "Fall" if velocity.y < 0 else "Jump"
elif speed > 0.1:
new_state = "Run" if speed > run_threshold else "Walk"
# Only transition if the target state exists
if state_machine.has_state(new_state):
state_machine.travel(new_state)
anim_tree.set("parameters/Move/speed", speed)
anim_tree.process(delta)
```
### Transition Conditions
Set transition conditions in the AnimationTree editor:
- **Blend**: Use blend amounts based on parameters (e.g., speed)
- **One Shot**: Play once then return (for attacks, interactions)
- **Transition Rules**: Define when transitions are allowed
## Blend Spaces
### 1D Blend Space
Use for animations ordered along a single axis (e.g., walk speed).
```gdscript
# AnimationTree setup:
# BlendSpace1D: Walk -> Run -> Sprint
# Parameter: "speed" (float)
anim_tree.set("parameters/BlendSpace1D/speed", current_speed)
```
### 2D Blend Space
Use for directional movement blending.
```gdscript
# AnimationTree setup:
# BlendSpace2D: X = speed, Y = direction blend
# Parameters: "speed" and "direction"
anim_tree.set("parameters/BlendSpace2D/speed", velocity.length())
anim_tree.set("parameters/BlendSpace2D/direction", velocity.angle())
```
### Directional Blend Space (Godot 4.x)
Use a directional blend for 8-directional character animations.
```gdscript
# Set up AnimationNodeBlendDBone2D for directional blending
@onready var anim_tree = $AnimationTree
func _physics_process(delta: float):
var dir = velocity.normalized()
anim_tree.set("parameters/Directional/speed", velocity.length())
anim_tree.set("parameters/Directional/direction", dir)
anim_tree.process(delta)
```
## Animation Libraries and Blending Tracks
### Animation Libraries
Group related animations into libraries for organization.
```gdscript
# Access library animations by name
@onready var anim_player = $AnimationPlayer
func play_animation(anim_name: String):
# Animations are organized by library in the editor
anim_player.play(anim_name)
# List available animations
func get_available_animations() -> Array:
return anim_player.get_animation_list()
```
### Blending Tracks
Blend between multiple animation tracks for smooth transitions.
```gdscript
# Set blend amount in AnimationTree
anim_tree.set("parameters/Idle/blend_amount", 1.0)
# Blend between two animations
anim_player.play("idle", -1.0, 1.0) # loop, 1s fade-in
anim_player.play("walk", -1.0, 0.5) # loop, 0.5s fade-in
# Crossfade by playing both simultaneously
# The AnimationTree blend space handles the mixing
```
## Root Motion for Character Movement
### Using Root Motion in AnimationTree
Root motion applies bone animation directly to the character transform.
```gdscript
class_name RootMotionCharacter extends CharacterBody3D
@onready var anim_tree = $AnimationTree
@onready var anim_state = anim_tree.get("state_machine")
@export var root_motion_enabled: bool = true
func _physics_process(delta: float):
# Calculate root motion displacement
var prev_transform = global_transform
# Process animation tree (applies root motion)
anim_tree.process(delta)
if root_motion_enabled:
var root_delta = global_transform.xform_inv(prev_transform)
velocity = Vector3(root_delta.origin.x / delta, 0, root_delta.origin.z / delta)
else:
# Use scripted movement instead
velocity = transform.basis.z * speed
move_and_slide()
```
### When to Use Root Motion
- Platformer jump arcs (precise landing positions)
- Attack animations with fixed reach distances
- Cutscene character movements
### When to Avoid Root Motion
- Multiplayer games (server authority conflicts)
- Characters that need precise position control
- Games with custom physics responses
## Godot 4.7 Animation Features
### Collapsible Animation Tracks
Godot 4.7 introduces collapsible animation tracks for better organization in the AnimationPlayer editor.
```gdscript
# No code change needed — this is an editor feature
# In the AnimationPlayer inspector, click track headers to collapse/expand
# Group related properties under collapsible sections
```
### tween_await() for Sequential Animations
Use await with tweens for clean sequential animation chains.
```gdscript
func play_combo_animation():
# Chain animations without nested callbacks
await create_tween().tween_property($Sprite, "offset:x", 10.0, 0.1).finished
await create_tween().tween_property($Sprite, "offset:x", 0.0, 0.1).finished
print("Combo animation complete")
# Or with AnimationPlayer
func play_with_wait():
var tween = create_tween()
anim_player.play("attack")
await tween.tween_interval(0.5)
anim_player.play("recovery")
```
## Animation Performance Tips
- Use **AnimationTree** with state machines instead of multiple AnimationPlayers
- Keep animation libraries small and focused
- Use **AnimationNodeSync** to synchronize multiple character animations
- Preload animation resources with preload() for always-needed scenes
- Avoid animating properties that can be set directly (e.g., position vs tween)
- Use `animation_finished` signal instead of polling for completion
## Quick Reference: Animation Methods
| Method | Use Case |
|--------|----------|
| `anim_player.play(name)` | Start an animation |
| `anim_player.play(name, fade_time)` | Crossfade to animation |
| `anim_tree.process(delta)` | Update state machine |
| `anim_tree.set("params/...", value)` | Set blend parameters |
| `state_machine.travel(name)` | Switch to a state |
| `create_tween()` | Create animation tweens |
| `await tween.finished` | Wait for tween completion |
## MCP Bridge Tools (Optional — Live Editor Integration)
When the MCP bridge is running (Phase 2), these tools enhance animation debugging:
- **`animation_play`** — Play any animation from the project without opening the editor
- **`animation_list`** — List all available animations and their libraries
- **`animation_state_get`** — Query current AnimationTree state machine status
- **`animation_preview_frame`** — Preview a specific frame of any animation
> **Note:** MCP tools require the Godot editor to be running with the MCP plugin enabled. Skills work independently without the bridge.
## References
- [AnimationPlayer Documentation](references/animationplayer-guide.md)
- [AnimationTree State Machine Patterns](references/animationtree-states.md)
- [Blend Space Design Guide](references/blend-spaces.md)