procedural-animation is a skill from the Summer skill library: a guide your AI agent reads when the task matches, so it builds the good version on the first try. Runtime bone changes on top of clips: head look-at, foot IK, hand grabs a prop, lean, recoil.
When your agent uses it
- The user needs runtime-driven bone modification on top of clips — head look-at, foot IK on uneven ground, additive lean, hit recoil, ragdoll
- The character’s feet float above or sink into stairs and slopes (foot placement)
Install
summer setup installs every skill for your agent. To add only this one:
claude-code for your agent, such as codex or cursor. See Skills for every option.
The skill
Generated clips cover most of a character’s motion. The rest — the eye contact when an NPC speaks, feet that plant on slopes, hands that wrap a sword grip, the lean into a sprint, the recoil from a hit on the left shoulder — is procedural. In Summer Engine this is done via theSkeletonModifier3D family attached to the Skeleton3D, plus additive blend layers on the AnimationTree. None of it is generative; this skill is a set of recipes.
Limit: Summer Engine’s current IK is good enough for look-at, foot-snap,
and simple two-bone arm/leg chains. It is not a full-body IK system with weight
redistribution. For combat-grappling or contact-heavy interactions, hand-author
the contact frame and accept some clipping.
When to use this skill
- Feet clip into / float over uneven terrain.
- NPC head doesn’t track the player during conversation — feels dead-eyed.
- Character’s hand doesn’t actually hold the sword — pen-through.
- Body doesn’t lean into turns / aiming.
- Hit reactions need to come from the hit direction (recoil left when struck left), not just one canned animation.
- Ragdoll on death.
When NOT to use this skill
- The clip already covers it. Don’t IK what mocap already nailed — adds CPU cost and rounding error.
- The character is far from the camera (LOD2+). Procedural cost outpaces visual benefit. Disable modifiers past 15m.
- You need facial animation. That’s
facial-and-lipsync. - You haven’t generated base clips yet. Skeleton modifiers compose ON TOP of clips; without a base pose they’ll stack on T-pose and look wrong.
The three patterns
Almost every procedural request maps to one of these three. Pick the right one before writing code.Pattern A — SkeletonModifier3D (post-clip bone overrides)
Attached as a child ofSkeleton3D. Runs after the AnimationTree writes the pose, modifies specific bones in-place. Includes LookAtModifier3D and SkeletonIK3D. Cheap, deterministic, no animation graph dependency.
Pattern B — Additive AnimationNodeAdd2 layer in the tree
A clip recorded as a delta from base pose (e.g., a “lean left” clip that’s 0 at center, fully leaned at +1) added on top of locomotion. Driven by writingparameters/Add/blend_amount from script. Use for stylistic overlays — turning lean, aiming offset, breathing.
Pattern C — PhysicalBoneSimulator3D (ragdoll)
The skeleton hands off to physics on death. Bones becomePhysicalBone3D rigid bodies that fall under gravity and collide with the world. One-way: once ragdoll fires, you can’t easily blend back to clip-driven without snapping.
Pattern A recipes
A1 — Head look-at the player
The most common NPC liveliness fix. ctx lane (animation-tier engines): onesummer_run_script call creates the owned modifier and sets the props — prefer it over the 10-call CRUD chain below:
prop_warnings report entry instead of failing silently — read it. On an older engine the helper is a plain script error; fall back to plain GDScript in the same tool (confirm the bone names first with summer_inspect_node):
symmetry_limit and no secondary_rotation_axis property on
LookAtModifier3D — the real names are the ones above, and the secondary
rotation axis is derived, not set. Confirmed against the shipped 4.6.1 binary;
ClassDB.class_get_property_list("LookAtModifier3D") is the check if you’re
unsure of a name.
Drive the target each frame:
use_angle_limitation is the key setting, and it defaults to false — a stock LookAtModifier3D does not clamp at all, so the head can rotate 180° and the model looks possessed. Turn it on and set primary_limit_angle to ~80° (1.4 rad), which matches a human’s neck-only range; for a “whole-body turn” use it with the spine chain (next recipe). primary_limit_angle defaults to 2π, i.e. unlimited.
A2 — Spine + head chain (look-at with body turn)
MultipleLookAtModifier3D nodes on the same chain — one for Spine1 (primary_limit_angle 0.4 rad), one for Spine2 (0.4 rad), one for Head (1.0 rad), each with use_angle_limitation = true. Total reach: ~110°, distributed naturally. Without the spine contribution, big angles look like the head detaches.
A3 — Foot IK (slopes & uneven terrain)
The clip has the foot at Y=0; on a slope the ground is at Y=0.15. Without IK, the foot floats. UseSkeletonIK3D on each two-bone leg chain:
min(left_offset, right_offset)) so the body squats and the legs don’t over-extend.
A4 — Hand grab on prop (sword grip, rifle stock)
SkeletonIK3D on the arm chain (Shoulder → UpperArm → LowerArm → Hand), with target_node set to a Marker3D parented to the prop. The clip drives the body; IK pins the hand to the grip. For a rifle held two-handed, do the right hand from clip and IK the left hand to a foregrip Marker3D — locks them together regardless of recoil.
Pattern B — Additive layer
In the AnimationTree, wrap Locomotion in anAnimationNodeAdd2:
parameters/Locomotion/Add/blend_amount (0..1) from script. Use cases: turn-lean (lean amount = clamp(turn_rate, -1, 1)), aim offset (lean while aiming up/down), breathing-while-idle. The lean clip must be authored as a delta from the base pose, or the pose is applied twice.
Pattern C — Ragdoll on death
Confirmation gates
- Before adding modifiers: state which bones, which axes. Bone-name typos are a top failure.
- Before driving from script: confirm influence will fade out at distance and the target node is correct.
- Before enabling ragdoll: confirm physical bones exist; without them, simulation is a no-op.
Reference card
Bone names (Meshy humanoid skeleton, exact strings)
Hips, Spine, Spine1, Spine2, Neck, Head, LeftShoulder, LeftArm, LeftForeArm, LeftHand, RightShoulder, RightArm, RightForeArm, RightHand, LeftUpLeg, LeftLeg, LeftFoot, LeftToeBase, RightUpLeg, RightLeg, RightFoot, RightToeBase. (Meshy uses Mixamo-compatible naming with no mixamorig: prefix.)
Axis conventions
Influence fade-out distances (tuned defaults)
Pitfalls
- LookAt rotates wildly / no clamp at all.
use_angle_limitationis false by default andprimary_limit_angledefaults to 2π. Set both. ~80° (1.4 rad) for a head-only modifier; ~25° (0.4 rad) for a single spine bone. - IK pops on the first frame. Solver hasn’t been initialized. Call
ik.start()after the AnimationTree’s first tick, not in_ready()— the bone pose is identity until the tree runs. - Foot IK pushes the body up on stairs but the camera doesn’t follow. Camera is parented to the root, not the head. Either parent the camera to a chest bone via
BoneAttachment3D, or accept that the camera doesn’t bob with foot IK. - Additive layer doubles the clip. The “additive” clip wasn’t authored as a delta from the base pose. Re-author it as a delta.
- Ragdoll just collapses, no spread. Missing per-bone impulse + missing collision shapes on hands/feet PhysicalBone3D children. Auto-generate via Skeleton3D inspector → “Create Physical Skeleton” with the “Add collisions” option.
- Modifiers run before the AnimationTree, not after. Modifier order is set by tree-position in the scene. SkeletonModifier3D nodes must be CHILDREN of Skeleton3D and appear AFTER any nodes that drive the pose. AnimationTree itself doesn’t sit under Skeleton3D — it sits at the character root and writes into Skeleton3D’s pose every frame.
- Look-at influence flickers at fade boundary. Use
lerp(current_influence, target, 5 * delta)instead of an instant assignment. Avoids the sub-pixel oscillation when the player walks the threshold.
Performance budget
- Each
LookAtModifier3D: ~5 µs/frame. Cheap; have many. - Each
SkeletonIK3Dtwo-bone solve: ~30 µs/frame. ~30 active solves per frame on mid-range desktop is fine; budget more conservatively on Steam Deck. - Ragdoll with full physical skeleton: ~200 µs/frame while simulating. Cap concurrent ragdolls at 5–8 before culling oldest.
Anti-patterns
- Writing
skel.set_bone_pose_position(...)in_process. Bypasses the AnimationTree, fights it next frame, results in jitter. Use modifiers instead; they run after the tree. (Edit-time STILL poses — a corpse, a statue — are the exception: no tree is running, soctx.bone_pose(skel, bone, {position/rotation/scale})on animation-tier engines, orset_bone_pose_*in a one-offsummer_run_script, is exactly right. Seecharacter-animation-wiring.) - Putting IK targets in worldspace and forgetting they don’t follow the character. Parent IK targets under the character root or bone — IK target is in the modifier’s local space.
- Procedural look-at without a fade-out at distance. Distant NPCs all snap to player every frame, looks like a hivemind.
- Foot IK on flying / floating characters. Disable when
is_on_floor() == false.
Edge cases
- Character is mounted (riding a horse). Disable foot IK on the rider; ride animation already sells the contact. Enable upper-body additive sway driven by horse acceleration.
- First-person hands. Same modifier set, but only the arm chain is visible — disable head/spine modifiers, keep hand-on-prop IK.
- Character is a quadruped. All four legs need foot IK. The bone names are different (
FrontLeftLeg,BackRightLeg, etc.); inspect first. - Network-synced ragdoll. Don’t simulate it on every client and don’t sync bones with
MultiplayerSynchronizer. In a Summer multiplayer game, send the few values that drive the ragdoll (the impulse, the moment it starts) as State or an Event and let each client simulate locally; seemultiplayer-state.
Fallback (no MCP)
Add modifiers in Summer Engine under Skeleton3D and set bone names from the Inspector dropdown, which autocompletes from the rig. Hand-write the GDScript driving them. Foot raycasts can be set up visually with a RayCast3D child.Handoff
- For the end-to-end rigged-character wiring these layers sit on top of (locomotion, method-track events, root motion),
character-animation-wiring. - For the AnimationTree these procedural layers compose with,
animation-tree. - For the source clips that procedural overlays modify,
generate-motion. - For face / lipsync (a different modifier family — BlendShapes, not bones),
facial-and-lipsync. - For NPC behavior triggering ragdoll on death,
design-npc. - For first-person aim sway / ADS,
fps-controller.
See also
- Upstream API reference matching the current Summer technical base:
SkeletonModifier3D,LookAtModifier3D,SkeletonIK3D,PhysicalBoneSimulator3D.
From a shell
No Summer MCP tools in this session? Run each one as a command; whensummer --version is missing or below 4.0, use npx -y summer-engine@latest in place of summer. Fields are flags in kebab-case (--scene-path res://main.tscn) or one --input '<json>', and summer ops describe <op> prints the exact input. The summer-cli skill has the rest.
Related skills
character-animation-wiring: Wire a rigged character end to end: real clips and bones, locomotion states, method tracks, root motion.design-npc: Design enemy, NPC, boss or companion behavior: perception, state machine, telegraphs, script stub.animation-tree: Wire AnimationTree state machines and blend trees: locomotion blends, attack interrupts, hit reactions.facial-and-lipsync: Make a character’s mouth move with a voice-over: phonemes, viseme blendshapes, facial expressions.generate-motion: Attach a library animation clip (idle, walk, run, attack) to a rigged character via AnimationPlayer.fps-controller: First-person controller: WASD, mouse look, jump, coyote time, jump buffering, air control.retarget: Apply animation clips from one rigged character to another: one clip library, many models.
Source:
library/skills/procedural-animation/SKILL.md, rendered from summer-engine@4.3.0 on npm.
