blender-animation
Animation in Blender 5.2 - slotted/layered actions and the channelbag API, Python keyframing, F-curves, game loops with pop/hitch checks, NLA clips, pose library, mocap/BVH/Mixamo retargeting with auto bone maps, baking control rigs to export skeletons, root motion, per-clip export. Use for any keyframe, action, NLA, mocap, or animation-export task.
Try your first task
A source-grounded starter task has not been verified for this skill yet.
SKILL.md
name: blender-animationdescription: Animation in Blender 5.2 - slotted/layered actions and the channelbag API, Python keyframing, F-curves, game loops with pop/hitch checks, NLA clips, pose library, mocap/BVH/Mixamo retargeting with auto bone maps, baking control rigs to export skeletons, root motion, per-clip export. Use for any keyframe, action, NLA, mocap, or animation-export task.license: MITmetadata: author: blender-agent-skills version: "1.2.0"Animation
The execution model is in blender-core (its references/bpy-patterns.md has verified keyframe/driver snippets). Rigs are in blender-character-rigging.
5.x data model (what changed)
- An Action holds slots (one per animated ID) and layers → strips → channelbags → F-curves. A single action can animate several objects (e.g. a rig and its camera) through different slots.
- Assign:
ob.animation_data.action = act, then make sureob.animation_data.action_slotis set (picked automatically when a suitable slot exists; otherwiseact.slots.new(id_type="OBJECT", name=ob.name)). - F-curves:
cb = anim_utils.action_ensure_channelbag_for_slot(act, slot), thencb.fcurves.ensure(path, index=i, group_name=...).action.fcurvesno longer exists. - The simplest route is still
pb.keyframe_insert("rotation_quaternion", frame=f), which creates the action, slot and channelbag.
Workflow (keyframe animation, studio style)
- Blocking: key poses on every channel (
CONSTANTinterpolation,bpy.context.preferences.edit.keyframe_new_interpolation_type) on golden frames (contact, down, passing, up for walks). - Breakdowns: add in-betweens that define arcs and spacing.
- Spline: switch to
BEZIER, fix spacing in the Graph Editor, and clean overshoot. Auto-clamped handles avoid overshoot. - Polish: offsets/overlap (follow-through on hair, tails, cloth bones), arcs, moving holds (never a perfectly frozen character), and contact stability (feet locked with IK).
- Review: MCP
look(mode="frames", frame_count=8)or a Workbench playblast (blender-rendering).
Game animation rules
- One action per clip, named
<Rig>_<Clip>or just<Clip>, with a fake user so it survives saving. - Loops: first and last frames identical. Export frames 1..N and let the engine drop the duplicate, or exclude the last frame (UE/Unity "loop pose" options). An F-curve
CYCLESmodifier helps preview but doesn't export, so bake it. Verify withscripts/loop_check.py -- --object RIG --action Walk [--root-motion root] [--fix]: it reports pose pops (last ≠ first, per bone, in deg/m) and speed hitches across the seam, and--fixkeys the first-frame values on the last frame (root travel is kept). - FPS: author at 30 (or 24) and let engines resample. Set
scene.render.fpsbefore importing mocap. - Root motion: the root bone carries the translation (and yaw). The hips keep the bob/sway.
scripts/bake_action.py --root-motion xymoves the hips' ground motion to the root. In-place clips: the root stays at the origin. - Additive/overlay clips (aim offsets, breathing) are exported as normal clips and marked additive in the engine.
- Keep the bone transform channels the engine expects. Don't animate bone scale unless the engine supports it (Roblox and many mobile pipelines don't).
Bake control rig → export skeleton
scripts/bake_action.py -- --list
scripts/bake_action.py -- --source RIG_Body --target GAME_RIG_Body [--actions Walk Run] [--root-motion xy --hips spine]
This gives one baked action per clip (GAME_RIG_Body|Walk), cleaned, with fake users, plus one muted NLA track per clip (CLIP_Walk) so FBX (bake_anim_use_nla_strips/all actions) and glTF (ACTIONS mode) export every clip. The target's constraints are muted afterward so it plays the baked data; run --follow to drive it live again. Self-bake (IK/constraints → keys on the same rig): --source X --target X.
Mocap and retargeting
- Import:
bpy.ops.import_anim.bvh(filepath=..., global_scale=0.01 if cm else 1, rotate_mode="NATIVE", update_scene_fps=True),import_scene.fbx(Mixamo,automatic_bone_orientation=True). - Retarget:
scripts/retarget.py -- --source Mocap --target GAME_RIG [--map auto|map.json] [--in-place] [--name Walk]. Each target bone gets the source bone's world rotation change from rest on its own rest orientation, so rolls, bone axes, Y-up/cm FBX object transforms and proportions don't matter. The hips travel is scaled by the hips-height ratio. Keys go straight into a newTARGET|Nameaction (quaternion, linear, fake user). Measured on a Mixamo-style rig (Y-up, 0.01 scale, rolled) → Rigify-named rig with 15% longer legs: 17 bones, < 0.1° error. - The auto map understands Mixamo (
mixamorig:LeftUpLeg), RigifyDEF-/ORG-, UE/Unity/BVH-style names, and spine chains of different lengths. Check it first with--show-map(unmapped_key_partsmust be empty), and pass a JSON{target: source}for anything custom (fingers, props). - Rest poses must match (T vs A matters most): pose the target's rest like the source's first. Then clean, add root motion, and export with
bake_action.py. - Clean mocap: decimate keys (
graph.decimate, ratio 0.3–0.5), use an F-curveSMOOTHmodifier or the Butterworth filter (graph.butterworth_smooth), and fix foot sliding with IK pins and then bake. - Production retarget tools: Auto-Rig Pro (paid), Rokoko (free), and the engine-side retargeters (UE IK Retargeter, Unity Humanoid).
NLA and pose library
- NLA: push actions down as strips (
track.strips.new(name, start, action)) to layer/blend clips (blend typeREPLACE/ADD/COMBINE), and use Tweak mode to edit. Strips need an action slot set when the action has several slots (strip.action_slot). - The pose library (bundled
pose_library) stores poses as assets:poselib.create_pose_asset(pose_name=...),poselib.apply_pose_asset/blend_pose_asset. Use it for hand shapes, face poses, and a T/A rest pose.
Shape keys and other properties
Any property can be keyed: kb.keyframe_insert("value", frame=f) (shape key), mat.node_tree.nodes[...].inputs[...].keyframe_insert("default_value") (materials, which engines usually ignore), custom props ob.keyframe_insert('["prop"]').
Gotchas
pb.matrix = ...followed bykeyframe_insertneeds the rightscene.frame_set(f)first, or an evaluation overwrites the pose.- Connected bones (
use_connect) can't translate. Hips/pelvis must be unconnected from the root. bake_actionwith visual keying reads evaluated poses, so constraints, IK and drivers are all captured. Mute the target's own constraints afterward (the script does), or they keep overriding the keys.- Quaternion vs Euler: game bones should use
QUATERNION(no gimbal lock, smooth slerp). Euler is fine for single-axis controls. Don't mix modes between keys. - glTF sampling:
export_force_samplingbakes every frame (the safe default). Non-linear F-curve modifiers and drivers only export when sampled.