Help us improve
Share bugs, ideas, or general feedback.
From summer
Wires Godot 4.5 AnimationTree state machines and blend spaces from existing clips. Activates when the user has idle/walk/run/attack clips and needs smooth transitions, hit reactions, or interrupts.
npx claudepluginhub summerengine/summer-engine-agent --plugin summerHow this skill is triggered — by the user, by Claude, or both
Slash command
/summer:animation-tree**/*.gd**/*.tscn**/*.tresThis skill is limited to the following tools:
The summary Claude sees in its skill listing — used to decide when to auto-load this skill
Generation gives you clips. The AnimationTree gives the character life. This skill is **not generative** — no FAL, no MCP AI calls. It composes existing clips on an `AnimationPlayer` into an `AnimationTree` with a `StateMachine` for distinct states (idle / attack / hit / dead) and `BlendSpace` nodes for continuous parameters (walk-run blend by speed). Done right, the character moves like a ship...
Provides GDScript and C# examples for Godot 4.3+ animations using AnimationPlayer for playback, AnimationTree for blending and state machines, sprite animation, and code-driven effects.
Generates animation clips (idle, walk, run, attack) from curated mocap library for Meshy-rigged humanoid characters. Wires clips to AnimationPlayer in Godot.
Unity 6 animation system guide. Use when working with Animator Controllers, animation state machines, blend trees, animation clips, Avatar system, humanoid rigs, root motion, animation events, Timeline, or Cinemachine. Based on Unity 6.3 LTS documentation.
Share bugs, ideas, or general feedback.
Generation gives you clips. The AnimationTree gives the character life. This skill is not generative — no FAL, no MCP AI calls. It composes existing clips on an AnimationPlayer into an AnimationTree with a StateMachine for distinct states (idle / attack / hit / dead) and BlendSpace nodes for continuous parameters (walk-run blend by speed). Done right, the character moves like a shipped game; done wrong, you get T-poses, snapping, or animations that "eat" each other.
The canonical Godot 4.5 stack:
Character (CharacterBody3D)
├── Skeleton3D (from the Meshy rig)
├── AnimationPlayer # holds the raw clips (idle, walk, run, attack_sword, ...)
└── AnimationTree # references AnimationPlayer, drives behavior
Before adding the tree, prove direct AnimationPlayer.play() visibly moves the rig. Godot may import animation GLBs as AnimationLibrary resources or as PackedScenes with embedded AnimationPlayers. If a copied clip appears in the list but the mesh T-poses, its tracks probably target a different root/skeleton path. Use the embedded player that came with the matching GLB, or remap/copy tracks only after confirming they target the active Skeleton3D. An inactive AnimationTree is also a no-op, so always set AnimationTree.active = true.
AnimationPlayer.play("walk") is causing pops, T-poses, or "starts halfway through".AnimationPlayer.play("loop") is fine.AnimationPlayer directly with play_with_capture; AnimationTree is overkill.summer:animation/generate-motion.summer:animation/procedural-animation.This is the production-default for a humanoid character that can move, attack, take a hit, and die. Start here, prune what you don't need, extend with named states for specials.
┌─────────┐
┌─────►│ Dead │ (terminal — no exit)
│ └─────────┘
│ ▲
│ │ on_death
┌──────────┴───────────┴──────────┐
│ Hit │ (one-shot, returns to prev)
└──────────▲──────────────────────┘
│ on_damaged ┌──────────┐
┌──────────┴──────────┐ │ Attack │ (one-shot)
│ Locomotion │ on_attack ──────►└──────────┘
│ (BlendSpace1D) │ ◄────── on_attack_done
│ idle ↔ walk ↔ run │
└─────────────────────┘
move_speed (0..max). Three points on the line: idle (0), walk (~3), run (~6). Crossfades for free.attack_sword (or whichever clip). Fires from the script via parameters/attack/request = ONE_SHOT_REQUEST_FIRE. Auto-returns to Locomotion when the clip ends.damaged signal.state_machine.travel("dead").summer_get_scene_tree
summer_inspect_node "./World/Goblin"
Confirm there's a Skeleton3D and an AnimationPlayer with at least idle + walk + run populated. If clips are missing, route to summer:animation/generate-motion.
summer_add_node(parent: "./World/Goblin", type: "AnimationTree", name: "AnimationTree")
summer_set_prop(path: "./World/Goblin/AnimationTree", key: "anim_player", value: "../AnimationPlayer")
summer_set_prop(path: "./World/Goblin/AnimationTree", key: "active", value: "true")
anim_player must be a relative NodePath; ../AnimationPlayer from a sibling. Don't use absolute paths — breaks scene reuse.
The tree_root is a single AnimationNodeStateMachine. Inside it, a Locomotion node which is itself an AnimationNodeBlendSpace1D, plus Attack, Hit, Dead nodes.
This is more readable to edit by hand or in the Godot editor, then commit the .tres. The MCP tool summer_set_resource_property can build it node-by-node, but the tree-resource model is verbose enough that writing the .tres and importing it is faster for the canonical structure. Skeleton:
[gd_resource type="AnimationNodeStateMachine" load_steps=8 format=3]
[sub_resource type="AnimationNodeBlendSpace1D" id="locomotion"]
blend_point_0/node = SubResource("idle_clip")
blend_point_0/pos = 0.0
blend_point_1/node = SubResource("walk_clip")
blend_point_1/pos = 3.0
blend_point_2/node = SubResource("run_clip")
blend_point_2/pos = 6.0
min_space = 0.0
max_space = 6.0
[sub_resource type="AnimationNodeOneShot" id="attack_oneshot"]
fadein_time = 0.05
fadeout_time = 0.10
mix_mode = 0 # 0=BLEND, 1=ADD
[sub_resource type="AnimationNodeOneShot" id="hit_oneshot"]
fadein_time = 0.0 # snap in — hit reactions are immediate
fadeout_time = 0.15
# ... AnimationNodeAnimation sub_resources point at clip names ...
[resource]
states/Locomotion/node = SubResource("locomotion")
states/Attack/node = SubResource("attack_oneshot")
states/Hit/node = SubResource("hit_oneshot")
states/Dead/node = SubResource("dead_clip")
transitions = [
"Locomotion", "Attack", SubResource("trans_to_attack"),
"Attack", "Locomotion", SubResource("trans_back"),
"Locomotion", "Hit", SubResource("trans_to_hit"),
"Attack", "Hit", SubResource("trans_to_hit"),
"Hit", "Locomotion", SubResource("trans_back"),
"Locomotion", "Dead", SubResource("trans_to_dead"),
"Attack", "Dead", SubResource("trans_to_dead"),
"Hit", "Dead", SubResource("trans_to_dead")
]
graph_offset = Vector2(0, 0)
Each AnimationNodeStateMachineTransition carries xfade_time (0.15 default), switch_mode (Immediate / Sync / At End), and advance_mode (Auto / Enabled / Disabled).
Ask before writing the .tres: "May I write res://characters/goblin/animation_tree.tres with the canonical 4-state machine + Locomotion blendspace?"
@onready var tree: AnimationTree = $AnimationTree
@onready var sm: AnimationNodeStateMachinePlayback = tree["parameters/playback"]
func _physics_process(delta: float) -> void:
var horiz_speed: float = Vector2(velocity.x, velocity.z).length()
tree.set("parameters/Locomotion/blend_position", horiz_speed)
func attack() -> void:
tree.set("parameters/Attack/request", AnimationNodeOneShot.ONE_SHOT_REQUEST_FIRE)
func take_hit() -> void:
tree.set("parameters/Hit/request", AnimationNodeOneShot.ONE_SHOT_REQUEST_FIRE)
func die() -> void:
sm.travel("Dead")
tree.set(...) writes a parameter path. sm.travel(...) switches state.
summer_connect_signal(
source: "./World/Goblin",
signal: "damaged",
target: "./World/Goblin",
method: "take_hit"
)
If the goblin has an HP component emitting died, connect that to die.
summer_save_scene
summer_get_script_errors
Then summer_play and watch — the goblin should idle in place, blend up to walk/run as it moves, fire attack on input/AI, snap to hit on damage, end in Dead.
.tres: show the state list and transition table.| Goal | Path |
|---|---|
| Set blendspace1D position | parameters/Locomotion/blend_position |
| Fire a OneShot | parameters/<NodeName>/request (set to ONE_SHOT_REQUEST_FIRE) |
| Abort a OneShot | parameters/<NodeName>/request = ONE_SHOT_REQUEST_ABORT |
| Read OneShot active state | parameters/<NodeName>/active |
| Get StateMachine playback | parameters/playback (returns AnimationNodeStateMachinePlayback) |
| Switch state | state_machine.travel("StateName") |
| Read current state | state_machine.get_current_node() |
| Force state without transition | state_machine.start("StateName") |
switch_mode decisionattack_1 → attack_2 only at end of attack_1).AnimationTree.active = true was missed. Set it in _ready() or via inspector.blend_position parameter isn't being written — confirm tree.set("parameters/Locomotion/blend_position", speed) runs every frame in _physics_process. Also confirm the path matches your state name exactly (case-sensitive).switch_mode is Immediate. Set to Sync so the cycle phase matches across the crossfade.Input.is_action_just_pressed, not is_action_pressed. Or store a _can_attack flag with cooldown.fadein_time = 0.0 and gate from script: if sm.get_current_node() == "Hit": return.mix_mode is BLEND (full body). For upper-body-only attacks, set mix_mode = ADD and use an additive clip (recorded as the offset from idle), or split the rig with a SkeletonModification3D mask.if is_dead: return.AnimationPlayer.play("walk") from script. Works for one clip; breaks the moment you need a crossfade.parameters/Attack/animation..tres by hand without using sub_resource IDs — Godot loses references and the inspector is unhappy. Always use [sub_resource id="..."] blocks.blend_position from raw input (Input.get_axis(...)). Drive from actual velocity — that way the blend matches the body's real motion, including knockback and slope-slide.root_motion_track on the AnimationTree (path to the root bone), then in _physics_process use tree.get_root_motion_position() and apply to the CharacterBody3D. Don't combine with input-driven velocity — pick one.Open the scene in Godot 4.5 editor, add AnimationTree node, set Anim Player to the AnimationPlayer, set Active = on, double-click Tree Root and edit visually. Drag AnimationNodeStateMachine as the root, drop nodes inside, draw transitions by Shift-dragging. Save the scene. The visual editor produces the same .tres — slower but discoverable.
summer:ai-and-npcs/design-npc.summer:character-controllers/fps-controller for the state inputs.summer:animation/procedural-animation.summer:animation/facial-and-lipsync.summer:animation/generate-motion — produce the clips this tree references.summer:animation/retarget — share one tree across many characters.references/gd-style.md — typed GDScript conventions in the controller snippets.references/mcp-tools-reference.md — summer_connect_signal and summer_set_resource_property rules.