| name | godot-2d-animation |
| description | Expert patterns for 2D animation in Godot using AnimatedSprite2D and skeletal cutout rigs. Use when implementing sprite frame animations, procedural animation (squash/stretch), cutout bone hierarchies, or frame-perfect timing systems. Trigger keywords: AnimatedSprite2D, SpriteFrames, animation_finished, animation_looped, frame_changed, frame_progress, set_frame_and_progress, cutout animation, skeletal 2D, Bone2D, procedural animation, animation state machine, advance(0). |
NEVER Do
- NEVER use AnimatedTexture โ This class is deprecated, highly inefficient in modern renderers, and may be removed in future Godot versions. Use AnimatedSprite2D or AnimationPlayer instead.
- NEVER allow Tweens to fight over the same property โ If multiple Tweens animate the same property, the last one created forcibly takes priority. Always assign your Tween to a variable and call
kill() on the previous instance before creating a new one.
- NEVER process kinematic movement outside the physics tick โ If your AnimationPlayer moves a CharacterBody2D, ensure the AnimationPlayer's callback mode is set to Physics. Animating physics bodies during the Idle (render) frame breaks fixed timestep physics interpolation and causes stutter.
- NEVER use
animation_finished for looping animations โ The signal only fires on non-looping animations. Use animation_looped instead for loop detection.
- NEVER call
play() and expect instant state changes โ AnimatedSprite2D applies play() on the next process frame. Call advance(0) immediately after play() if you need synchronous property updates (e.g., when changing animation + flip_h simultaneously).
- NEVER set
frame directly when preserving animation progress โ Setting frame resets frame_progress to 0.0. Use set_frame_and_progress(frame, progress) to maintain smooth transitions when swapping animations mid-frame.
- NEVER forget to cache
@onready var anim_sprite โ The node lookup getter is surprisingly slow in hot paths like _physics_process(). Always use @onready.
- NEVER mix AnimationPlayer tracks with code-driven AnimatedSprite2D โ Choose one animation authority per sprite. Mixing causes flickering and state conflicts.
- NEVER use paper-thin skeletons for deformation โ 2D meshes require balanced vertex density. If your mesh deforms poorly, increase the vertex count near joints in the Mesh2D editor.
Available Scripts
MANDATORY: Read the script for the pattern you are implementing. Inline recipes that duplicated these scripts were removed โ the script is the source of truth.
Do NOT Load (by scenario)
| Scenario | Load | Do NOT Load |
|---|
| Single character / player | one_frame_sync_fix.gd, animation_state_sync.gd, optional animation_tree_step.gd / tween_lifecycle_manager.gd | multimesh_swarm_anim.gd, gpu_mesh_optimizer.gd (unless fill-rate profiling demands it) |
| Frame events / hitboxes / SFX sync | animation_sync.gd (+ AnimationPlayer method tracks) | Swarm/MultiMesh scripts |
| Squash/stretch game-feel | MANDATORY procedural_squash_stretch.gd | Inline landing-condition snippets in this skill |
| Cutout / IK limbs | skeleton_2d_rig_helper.gd | MultiMesh swarm scripts |
| Shader flash / dissolve on anim | shader_hook.gd | โ |
| Thousands of bats/fish/props | multimesh_swarm_anim.gd (+ docs fish tutorial) | Per-entity AnimatedSprite2D / Tween managers |
Script index
Expert Decision Tree: Choosing the Right Animation Tool
| Scenario | Recommended Node | Expert Insight |
|---|
| Isolated, pure frame-by-frame spritesheets | AnimatedSprite2D | Cannot animate non-visual properties or method tracks โ escalate to AnimationPlayer when you need those. |
| Cutout animations, non-visual sync, audio/particles | AnimationPlayer | Owns transforms, mesh deformation, method/value tracks. |
| Complex state machines, blending, locomotion | AnimationTree | Logic graph over an AnimationPlayer; use travel() via animation_tree_step.gd. |
| Procedural, dynamic, fire-and-forget UI/fx | Tween | Runtime targets; always go through tween_lifecycle_manager.gd. |
| Swarms of thousands of entities | MultiMeshInstance2D + Shader | Load multimesh_swarm_anim.gd only; skip character sync scripts. |
Golden Path: One-Frame Sync (play + advance(0))
When changing animation and sprite properties in the same frame, play() alone applies next process tick โ one-frame glitch.
MANDATORY: Read one_frame_sync_fix.gd. Minimal contract:
# After any play() that must match flip/modulate/etc. this frame:
anim.flip_h = dir < 0
anim.play(&"run")
anim.advance(0) # force pose now
Related: animation_looped (loops) vs animation_finished (one-shots); use set_frame_and_progress when swapping skins mid-clip (see AnimatedSprite2D class docs).
Procedural Squash & Stretch
Do NOT paste landing snippets into agents. A prior body used an impossible condition (not is_on_floor() and is_on_floor()).
MANDATORY sole source: procedural_squash_stretch.gd โ impact squash, velocity stretch, lerp recovery. Pair with godot-characterbody-2d / godot-2d-physics for floor/velocity authority.
Quick routing (scripts own the recipes)
- Tween interrupt / flash loops โ
tween_lifecycle_manager.gd (never race two Tweens on one property).
- AnimationTree travel โ
animation_tree_step.gd (start then travel).
- IK foot plant โ
skeleton_2d_rig_helper.gd + SkeletonModification2DTwoBoneIK docs.
- Fill-rate / swarms โ
gpu_mesh_optimizer.gd / multimesh_swarm_anim.gd per Do-NOT-Load table.
- Pixel filter / shared SpriteFrames โ Official Documentation (2D sprite animation, SpriteFrames); keep resources shared via preload.
Expert insights (WHY โ keep in body)
- Hybrid cutout + cel โ Animate bones for body motion; keyframe
frame/texture on child sprites for hand/face swaps. WHY: transform-only motion is cheap; cel swaps stay art-directable without re-rigging.
- GPU fill rate โ Large transparent sprites waste fill rate. WHY: tight
MeshInstance2D polygons skip transparent texels; pair with gpu_mesh_optimizer.gd.
- Tween property fights โ WHY: the last Tween on a property wins silently. Always
kill() the prior instance (tween_lifecycle_manager.gd).
- AnimationTree travel โ WHY: StateMachine uses internal A* between states; call
start() before travel() (animation_tree_step.gd).
Deep recipes (on demand)
Reference
Progressive disclosure: open Official Documentation links only when researching a specific API;
load Related Skills when routing work to a peer domain โ do not preload the whole lattice.
Official Documentation
- 2D sprite animation โ Canonical AnimatedSprite2D + SpriteFrames workflow for frame-based sheets and signal timing.
- Introduction to the animation features โ When to graduate from spritesheets to AnimationPlayer for tracks, methods, and non-visual properties.
- Cutout animation โ Paper-doll hierarchies and hybrid cutout/cel setups before full skeletal IK.
- 2D skeletons โ Skeleton2D / Bone2D rigging, rest poses, and deformation expectations for cutout meshes.
- Using AnimationTree โ Blend spaces and state-machine graphs that drive an underlying AnimationPlayer.
- Animation track types โ Method/value/property tracks for frame-perfect SFX, hitboxes, and shader uniform hooks.
- AnimatedSprite2D โ
play(), advance(), set_frame_and_progress(), and animation_looped vs animation_finished contracts.
- SpriteFrames โ Shared frame resources, loop flags, and per-animation timing used by AnimatedSprite2D.
- Tween โ Runtime squash/stretch and interruptible one-shot motion without baking AnimationPlayer clips.
- Animating thousands of fish โ GPU vertex / MultiMesh patterns for swarm motion that must leave the node tree.
- SkeletonModification2DTwoBoneIK โ Lightweight two-bone IK for procedural foot/hand planting on Skeleton2D stacks.
Related Skills
Prerequisites
- godot-animation-player โ AnimationPlayer ownership, callback modes, and track authoring that this skillโs hybrid/cutout patterns assume.
- godot-characterbody-2d โ Physics-tick movement so animated CharacterBody2D motion stays on the fixed timestep.
- godot-signal-architecture โ Safe wiring for
animation_finished / animation_looped / frame_changed without lifecycle leaks.
Complements
- godot-animation-tree-mastery โ Deepen blend trees, OneShot layers, and
travel() pathfinding beyond the 2D locomotion basics here.
- godot-tweening โ Broader Tween composition when squash/stretch or UI pops outgrow inline
create_tween() snippets.
- godot-shaders-basics โ CanvasItem shader uniforms driven by AnimationPlayer tracks or MultiMesh swarm materials.
- godot-2d-physics โ Impact velocity, raycasts for IK targets, and interpolation rules that feed procedural deformation.
- godot-state-machine-advanced โ Gameplay FSMs that should own intent while AnimationTree/AnimatedSprite2D own presentation.
- godot-particles โ Dust, hit sparks, and trails spawned from method tracks or frame events.
- godot-adapt-3d-to-2d โ Directional sheets, billboards, and fake-depth sorting that still use 2D animation nodes.
Downstream / consumers
- godot-genre-platformer โ Jump/land/run presentation stacks consume sync, squash/stretch, and state-machine travel patterns.
- godot-genre-fighting โ Frame-perfect hitboxes and method tracks depend on AnimationPlayer + AnimatedSprite2D discipline here.
- godot-resource-data-patterns โ Shared
.tres SpriteFrames and skin packs for memory-safe multi-instance characters.
Master
- godot-master โ Library router and mirrored module entry for cross-skill discovery.