Advanced animation blending, state machines, and blend spaces with AnimationTree
The AnimationTree node provides advanced animation capabilities beyond what AnimationPlayer offers. It enables complex animation blending, state machines, blend spaces, and layered animation control.
AnimationTree works alongside an AnimationPlayer. The AnimationPlayer stores the animations, while AnimationTree controls how they blend and transition.
# Get the state machine playbackvar state_machine = $AnimationTree.get("parameters/playback")# Travel to a statestate_machine.travel("walk")# Start from a specific statestate_machine.start("idle")# Stop the state machinestate_machine.stop()# Get current statevar current = state_machine.get_current_node()print("Current state: ", current)
# Set a parameter for transition conditions$AnimationTree.set("parameters/conditions/is_moving", true)# The transition with advance_condition = "is_moving" will trigger
Blend animations along a single axis (e.g., walk to run speed):
var blend_space_1d = AnimationNodeBlendSpace1D.new()blend_space_1d.min_space = 0.0blend_space_1d.max_space = 10.0# Add animations at different pointsblend_space_1d.add_blend_point(idle_node, 0.0)blend_space_1d.add_blend_point(walk_node, 5.0)blend_space_1d.add_blend_point(run_node, 10.0)# Set blend position (0.0 to 10.0)$AnimationTree.set("parameters/Movement/blend_position", 7.5)
Plays a one-shot animation over the base animation:
# Trigger a one-shot animation (e.g., attack)$AnimationTree.set("parameters/OneShot/request", AnimationNodeOneShot.ONE_SHOT_REQUEST_FIRE)# Or use shorter form$AnimationTree.set("parameters/OneShot/active", true)# Check if one-shot is playingvar is_active = $AnimationTree.get("parameters/OneShot/active")
# Switch to animation index 2$AnimationTree.set("parameters/Transition/current_index", 2)# Get current indexvar current = $AnimationTree.get("parameters/Transition/current_index")
Extract movement from animations for character controllers:
# Enable root motion on the AnimationTree$AnimationTree.root_motion_track = NodePath("Skeleton3D:Root")# Get root motion in _process or _physics_processvar root_motion = $AnimationTree.get_root_motion_position()velocity += root_motion / delta# Get rotationvar root_rotation = $AnimationTree.get_root_motion_rotation()
Root motion allows animations to directly drive character movement, ensuring perfect synchronization between animation and gameplay.
Control which bones/properties are affected by specific nodes:
# Enable filtering on a nodevar add_node = AnimationNodeAdd2.new()add_node.filter_enabled = true# Only affect specific bones (e.g., upper body for shooting animation)add_node.set_filter_path(NodePath("Skeleton3D:Spine"), true)add_node.set_filter_path(NodePath("Skeleton3D:RightArm"), true)add_node.set_filter_path(NodePath("Skeleton3D:LeftArm"), true)