fix: make the character pipeline work end-to-end in Blender 5.1 + bundle CC0 animation library

Verified the full chain on a real Sketchfab model (Miku UID -> rigged ->
13 clips -> loads and animates in-engine, 24/24 smoke checks pass).

Fixes found while running it for real:
- sketchfab_import: read .sketchfab_token as UTF-16/BOM too (PowerShell's
  `echo >` writes UTF-16LE, which crashed the UTF-8 reader)
- autorig: rig to the animation library's OWN skeleton when _library.glb
  is present (zero retargeting); robust binding — fall back to rigid
  nearest-bone weights when Blender bone-heat fails on complex meshes
  (Miku's joined hair/clothing gave 0 weighted verts); export as
  parent_type=ARMATURE with no modifier (Blender 5.x only emits a glTF
  skin in that exact form — a lingering Armature modifier gave skins:0);
  export_apply=False (applying modifiers baked away the skin); flatten
  the Sketchfab empty hierarchy before binding
- merge_animations: support a single multi-clip library GLB via
  LIBRARY_CLIP_MAP; version-safe fcurve access for Blender 4.4+/5.x
  slotted actions (Action.fcurves was removed)

Assets/tooling:
- bundle assets/characters/animations/_library.glb — CC0 Quaternius
  Universal Animation Library (13 game clips), + .gdignore so Godot
  skips the pipeline-input folder
- requirements.txt (stdlib-only; documents Blender-python separation)
- pipeline docs updated for the bundled library + swap instructions

Co-Authored-By: Claude Fable 5 <[email protected]>
This commit is contained in:
Nicholas Butzke
2026-07-06 12:42:31 -04:00
co-authored by Claude Fable 5
parent d05477c135
commit 64bbbf93c6
11 changed files with 385 additions and 90 deletions
+27 -31
View File
@@ -17,9 +17,11 @@ menu dropdown, fully animated in first AND third person, synced in multiplayer.
Put it in the env var `SKETCHFAB_API_TOKEN`, or in a file named
`.sketchfab_token` in the project root (gitignored).
2. **Blender 3.6+** — on PATH, or set `BLENDER_PATH` to `blender.exe`.
3. **Animation library**fill `assets/characters/animations/` with one clip
per file on the Mixamo skeleton. This is done ONCE and reused for every
character forever. See "Building the animation library" below.
3. **Animation library**already bundled. `assets/characters/animations/_library.glb`
is the CC0 Quaternius Universal Animation Library (13 game-relevant clips
mapped in `LIBRARY_CLIP_MAP`). `tools/autorig.py` rigs every character to
this library's own skeleton, so clips apply with zero retargeting. To use a
different/larger set instead, see "Swapping the animation library" below.
## The pipeline, step by step
@@ -63,38 +65,32 @@ automation needs an alternative. In order of preference:
All roads lead to the same place: a GLB with Mixamo bone names, which is what
`merge_animations.py` and the game expect.
## Building the animation library (once)
## Swapping the animation library
The library lives in `assets/characters/animations/` — one clip per file,
filename = clip name (`idle.fbx``Idle`, `crouch_walk.fbx``CrouchWalk`).
`merge_animations.py` supports two library layouts in
`assets/characters/animations/`:
**Recommended: Mixamo clips.** Go to mixamo.com, pick the X Bot character,
download each clip as *FBX Binary, Without Skin, 30 fps* (use "In Place"
variants where offered):
**A. Multi-clip library GLB (the bundled default).** If `_library.glb` exists,
its clips are merged and mapped through `LIBRARY_CLIP_MAP` in
`tools/merge_animations.py`. The bundled file is the CC0 Quaternius Universal
Animation Library (13 clips: Idle, Walk, Run, Sprint, Jump, Fall, Land,
CrouchIdle, CrouchWalk, Dash, Death, Hit, Dance). **Important:** `autorig.py`
rigs characters to *this GLB's own skeleton*, so if you replace `_library.glb`
you must re-rig characters against the new one (the pipeline does this
automatically). To pull in more of Quaternius's 120-clip set, drop in the Pro
`_library.glb` and add rows to `LIBRARY_CLIP_MAP`.
| File | Mixamo search |
|---|---|
| `idle.fbx` | Rifle Idle (or Idle) |
| `walk.fbx` | Walking (In Place) |
| `run.fbx` | Rifle Run / Fast Run (In Place) |
| `sprint.fbx` | Sprint (In Place) |
| `jump.fbx` | Jump |
| `fall.fbx` | Falling Idle |
| `crouch_idle.fbx` | Crouch Idle |
| `crouch_walk.fbx` | Crouch Walk (In Place) |
| `slide.fbx` | Running Slide |
| `wall_run.fbx` | (see note) Run variant works fine |
| `dash.fbx` | Sprint or Dive |
| `death.fbx` | Dying |
**B. Loose one-clip-per-file (Mixamo).** Delete `_library.glb` and instead add
FBX/GLB files named by clip (`idle.fbx``Idle`, `crouch_walk.fbx`
`CrouchWalk`). Download from mixamo.com as *FBX Binary, Without Skin, 30 fps*
("In Place" variants). In this mode characters must be on the Mixamo skeleton
(rig via Mixamo web / AccuRig and pass `--rigged`, or let the heuristic
`build_mixamo_armature` fit one).
CC0 alternative: **Quaternius Universal Animation Library** (quaternius.com,
500+ clips, Mixamo-compatible skeleton) or **Kenney character assets**
both free for commercial use, no attribution required.
Missing clips are fine: the game falls back along sensible chains
(`Slide → CrouchIdle → Idle`, `WallRun → Run`, etc. — see
`CLIP_FALLBACKS` in `characters/skinned_player_model.gd`). A model with just
Idle/Walk/Run still animates in every movement state.
Missing clips are fine either way: the game falls back along sensible chains
(`Slide → CrouchIdle → Idle`, `WallRun → Run`, etc. — see `CLIP_FALLBACKS` in
`characters/skinned_player_model.gd`). A model with just Idle/Walk/Run still
animates in every movement state.
## How it works in-game