godot-animation-player

安装量: 60
排名: #12420

安装

npx skills add https://github.com/thedivergentai/gd-agentic-skills --skill godot-animation-player
AnimationPlayer
Expert guidance for Godot's timeline-based keyframe animation system.
NEVER Do
NEVER forget RESET tracks
— Without a RESET track, animated properties don't restore to initial values when changing scenes. Create RESET animation with all default states.
NEVER use Animation.CALL_MODE_CONTINUOUS for function calls
— Calls method EVERY frame during keyframe. Use CALL_MODE_DISCRETE (calls once). Continuous causes spam.
NEVER animate resource properties directly
— Animating
material.albedo_color
creates embedded resources, bloating file size. Store material in variable, animate variable's properties.
NEVER use animation_finished for looping animations
— Signal doesn't fire for looped animations. Use
animation_looped
or check
current_animation
in _process().
NEVER hardcode animation names as strings everywhere
— Use constants or enums. Typos cause silent failures.
Available Scripts
MANDATORY
Read the appropriate script before implementing the corresponding pattern. audio_sync_tracks.gd Sub-frame audio synchronization via Animation.TYPE_AUDIO tracks. Footstep setup with automatic blend handling for cross-fades. programmatic_anim.gd Procedural animation generation: creates Animation resources via code with keyframes, easing, and transition curves for dynamic runtime animations. Track Types Deep Dive Value Tracks (Property Animation)

Animate ANY property: position, color, volume, custom variables

var anim := Animation . new ( ) anim . length = 2.0

Position track

var pos_track := anim . add_track ( Animation . TYPE_VALUE ) anim . track_set_path ( pos_track , ".:position" ) anim . track_insert_key ( pos_track , 0.0 , Vector2 ( 0 , 0 ) ) anim . track_insert_key ( pos_track , 1.0 , Vector2 ( 100 , 0 ) ) anim . track_set_interpolation_type ( pos_track , Animation . INTERPOLATION_CUBIC )

Color track (modulate)

var color_track := anim . add_track ( Animation . TYPE_VALUE ) anim . track_set_path ( color_track , "Sprite2D:modulate" ) anim . track_insert_key ( color_track , 0.0 , Color . WHITE ) anim . track_insert_key ( color_track , 2.0 , Color . TRANSPARENT ) $AnimationPlayer . add_animation ( "fade_move" , anim ) $AnimationPlayer . play ( "fade_move" ) Method Tracks (Function Calls)

Call functions at specific timestamps

var method_track := anim . add_track ( Animation . TYPE_METHOD ) anim . track_set_path ( method_track , "." )

Path to node

Insert method calls

anim . track_insert_key ( method_track , 0.5 , { "method" : "spawn_particle" , "args" : [ Vector2 ( 50 , 50 ) ] } ) anim . track_insert_key ( method_track , 1.5 , { "method" : "play_sound" , "args" : [ "res://sounds/explosion.ogg" ] } )

CRITICAL: Set call mode to DISCRETE

anim . track_set_call_mode ( method_track , Animation . CALL_MODE_DISCRETE )

Methods must exist on target node:

func spawn_particle ( pos : Vector2 ) -> void :

Spawn particle at position

pass func play_sound ( sound_path : String ) -> void : $AudioStreamPlayer . stream = load ( sound_path ) $AudioStreamPlayer . play ( ) Audio Tracks

Synchronize audio with animation

var audio_track := anim . add_track ( Animation . TYPE_AUDIO ) anim . track_set_path ( audio_track , "AudioStreamPlayer" )

Insert audio playback

var audio_stream := load ( "res://sounds/footstep.ogg" ) anim . audio_track_insert_key ( audio_track , 0.3 , audio_stream ) anim . audio_track_insert_key ( audio_track , 0.6 , audio_stream )

Second footstep

Set volume for specific key

anim . audio_track_set_key_volume ( audio_track , 0 , 1.0 )

Full volume

anim . audio_track_set_key_volume ( audio_track , 1 , 0.7 )

Quieter

Bezier Tracks (Custom Curves)

For smooth, custom interpolation curves

var bezier_track := anim . add_track ( Animation . TYPE_BEZIER ) anim . track_set_path ( bezier_track , ".:custom_value" )

Insert bezier points with handles

anim . bezier_track_insert_key ( bezier_track , 0.0 , 0.0 ) anim . bezier_track_insert_key ( bezier_track , 1.0 , 100.0 , Vector2 ( 0.5 , 0 ) ,

In-handle

Vector2 ( - 0.5 , 0 ) )

Out-handle

Read value in _process

func _process ( delta : float ) -> void : var value := $AnimationPlayer . get_bezier_value ( "custom_value" )

Use value for custom effects

Root Motion Extraction Problem: Animated Movement Disconnected from Physics

Character walks in animation, but position doesn't change in world

Animation modifies Skeleton bone, not CharacterBody3D root

Solution: Root Motion

Scene structure:

CharacterBody3D (root)

├─ MeshInstance3D

│ └─ Skeleton3D

└─ AnimationPlayer

AnimationPlayer setup:

@ onready var anim_player : AnimationPlayer = $AnimationPlayer func _ready ( ) -> void :

Enable root motion (point to root bone)

anim_player . root_motion_track = NodePath ( "MeshInstance3D/Skeleton3D:root" ) anim_player . play ( "walk" ) func _physics_process ( delta : float ) -> void :

Extract root motion

var root_motion_pos := anim_player . get_root_motion_position ( ) var root_motion_rot := anim_player . get_root_motion_rotation ( ) var root_motion_scale := anim_player . get_root_motion_scale ( )

Apply to CharacterBody3D

var transform := Transform3D ( basis . rotated ( basis . y , root_motion_rot . y ) , Vector3 . ZERO ) transform . origin = root_motion_pos global_transform *= transform

Velocity from root motion

velocity

root_motion_pos / delta move_and_slide ( ) Animation Sequences & Queueing Chaining Animations

Play animations in sequence

@ onready var anim : AnimationPlayer = $AnimationPlayer func play_attack_combo ( ) -> void : anim . play ( "attack_1" ) await anim . animation_finished anim . play ( "attack_2" ) await anim . animation_finished anim . play ( "idle" )

Or use queue:

func play_with_queue ( ) -> void : anim . play ( "attack_1" ) anim . queue ( "attack_2" ) anim . queue ( "idle" )

Auto-plays after attack_2

Blend Times

Smooth transitions between animations

anim . play ( "walk" )

0.5s blend from walk → run

anim . play ( "run" , - 1 , 1.0 , 0.5 )

custom_blend = 0.5

Or set default blend

anim . set_default_blend_time ( 0.3 )

0.3s for all transitions

anim . play ( "idle" ) RESET Track Pattern Problem: Properties Don't Reset

Animate sprite position from (0,0) → (100, 0)

Change scene, sprite stays at (100, 0)!

Solution: RESET Animation

Create RESET animation with default values

var reset_anim := Animation . new ( ) reset_anim . length = 0.01

Very short

var track := reset_anim . add_track ( Animation . TYPE_VALUE ) reset_anim . track_set_path ( track , "Sprite2D:position" ) reset_anim . track_insert_key ( track , 0.0 , Vector2 ( 0 , 0 ) )

Default position

track

reset_anim . add_track ( Animation . TYPE_VALUE ) reset_anim . track_set_path ( track , "Sprite2D:modulate" ) reset_anim . track_insert_key ( track , 0.0 , Color . WHITE )

Default color

anim_player . add_animation ( "RESET" , reset_anim )

AnimationPlayer automatically plays RESET when scene loads

IF "Reset on Save" is enabled in AnimationPlayer settings

Procedural Animation Generation Generate Animation from Code

Create bounce animation programmatically

func create_bounce_animation ( ) -> void : var anim := Animation . new ( ) anim . length = 1.0 anim . loop_mode = Animation . LOOP_LINEAR

Position track (Y bounce)

var track := anim . add_track ( Animation . TYPE_VALUE ) anim . track_set_path ( track , ".:position:y" )

Generate sine wave keyframes

for i in range ( 10 ) : var time := float ( i ) / 9.0

0.0 to 1.0

var value := sin ( time * TAU ) * 50.0

Bounce height 50px

anim . track_insert_key ( track , time , value ) anim . track_set_interpolation_type ( track , Animation . INTERPOLATION_CUBIC ) $AnimationPlayer . add_animation ( "bounce" , anim ) $AnimationPlayer . play ( "bounce" ) Advanced Patterns Play Animation Backwards

Play animation in reverse (useful for closing doors, etc.)

anim . play ( "door_open" , - 1 , - 1.0 )

speed = -1.0 = reverse

Pause and reverse

anim . pause ( ) anim . play ( "current_animation" , - 1 , - 1.0 , false )

from_end = false

Animation Callbacks (Signal-Based)

Emit custom signal at specific frame

func _ready ( ) -> void : $AnimationPlayer . animation_finished . connect ( _on_anim_finished ) func _on_anim_finished ( anim_name : String ) -> void : match anim_name : "attack" : deal_damage ( ) "die" : queue_free ( ) Seek to Specific Time

Jump to 50% through animation

anim . seek ( anim . current_animation_length * 0.5 )

Scrub through animation (cutscene editor)

func _input ( event : InputEvent ) -> void : if event is InputEventMouseMotion and scrubbing : var normalized_pos := event . position . x / get_viewport_rect ( ) . size . x anim . seek ( anim . current_animation_length * normalized_pos ) Performance Optimization Disable When Off-Screen extends VisibleOnScreenNotifier2D func _ready ( ) -> void : screen_exited . connect ( _on_screen_exited ) screen_entered . connect ( _on_screen_entered ) func _on_screen_exited ( ) -> void : $AnimationPlayer . pause ( ) func _on_screen_entered ( ) -> void : $AnimationPlayer . play ( ) Edge Cases Animation Not Playing

Problem: Forgot to add animation to player

Solution: Check if animation exists

if anim . has_animation ( "walk" ) : anim . play ( "walk" ) else : push_error ( "Animation 'walk' not found!" )

Better: Use constants

const ANIM_WALK = "walk" const ANIM_IDLE = "idle" if anim . has_animation ( ANIM_WALK ) : anim . play ( ANIM_WALK ) Method Track Not Firing

Problem: Call mode is CONTINUOUS

Solution: Set to DISCRETE

var
method_track_idx
:=
anim
.
find_track
(
".:method_name"
,
Animation
.
TYPE_METHOD
)
anim
.
track_set_call_mode
(
method_track_idx
,
Animation
.
CALL_MODE_DISCRETE
)
Decision Matrix: AnimationPlayer vs Tween
Feature
AnimationPlayer
Tween
Timeline editing
✅ Visual editor
❌ Code only
Multiple properties
✅ Many tracks
❌ One property
Reusable
✅ Save as resource
❌ Create each time
Dynamic runtime
❌ Static
✅ Fully dynamic
Method calls
✅ Method tracks
❌ Use callbacks
Performance
✅ Optimized
❌ Slightly slower
Use AnimationPlayer for
Cutscenes, character animations, complex UI
Use Tween for
Simple runtime effects, one-off transitions Reference Master Skill: godot-master
返回排行榜