Use when building or refining Junipali 3D stages/characters in Blender and exporting production-ready GLB assets for the game runtime. Covers scene scale, rig/animation export, naming conventions, and handoff checklist.
Resources
18Install
npx skillscat add temisangerrard/autonomous-arena-scaffold Install via the SkillsCat registry.
Blender World Build
Use this skill when the task involves Blender scene work, world building, stage set dressing, character rig updates, Mixamo/FBX import, or GLB export troubleshooting.
Source Of Truth In This Project
When working on Junipali, follow the local Python workflows first:
/Users/temisan/Downloads/junipali-game/blender_tools/stage_builder.py/Users/temisan/Downloads/junipali-game/blender_tools/export_tools.py/Users/temisan/Downloads/junipali-game/blender_tools/animation_tools.py/Users/temisan/Downloads/junipali-game/blender_tools/character_rigger.py/Users/temisan/Downloads/junipali-game/BLENDER_WORKFLOWS.md/Users/temisan/Downloads/FBX files/blender_python_reference_5_0(Blender 5.0 API reference)/Users/temisan/.codex/skills/blender-world-build/references/blender-5-api-index.md(task-to-API map)/Users/temisan/.codex/skills/blender-world-build/references/world-build-capabilities.md(broad capability map)/Users/temisan/.codex/skills/blender-world-build/references/blender-5-api-manifest.json(machine-generated API manifest, 1862 pages indexed)/Users/temisan/.codex/skills/blender-world-build/scripts/generate_blender_api_manifest.py(rebuild manifest)/Users/temisan/.codex/skills/blender-world-build/scripts/query_blender_api_manifest.py(search manifest)
If these local files conflict with generic Blender habits, prefer the local files.
How To Use This Skill For Natural-Language Blender Work
- Map user request to task in:
/Users/temisan/.codex/skills/blender-world-build/references/blender-5-api-index.md/Users/temisan/.codex/skills/blender-world-build/references/world-build-capabilities.md
- Query the machine manifest for candidate operators/types.
- Pull the exact operator/type docs from local Blender reference.
- Implement script/operator calls with Blender 5 action compatibility.
- Validate output in runtime (GLB loads, rig moves mesh, clips play).
For broad world-building asks, use capability routing first, then specific API pages.
Manifest refresh command:
python3 /Users/temisan/.codex/skills/blender-world-build/scripts/generate_blender_api_manifest.py --doc-root '/Users/temisan/Downloads/FBX files/blender_python_reference_5_0' --out /Users/temisan/.codex/skills/blender-world-build/references/blender-5-api-manifest.json
Manifest query command:
python3 /Users/temisan/.codex/skills/blender-world-build/scripts/query_blender_api_manifest.py --manifest /Users/temisan/.codex/skills/blender-world-build/references/blender-5-api-manifest.json --q "import_scene.fbx" --limit 20
Blender 5.0 API Compatibility (From Local Reference)
The local reference confirms Blender 5.x moved Action internals to layered data:
Action.is_action_legacymay beFalseeven for valid imported actions.- F-curves/groups can live on channelbags, not on
action.fcurves/action.groups. - Important types:
Action.slots,Action.layers,ActionChannelbag.fcurves,ActionChannelbag.groups.
Use this safe iteration pattern in scripts:
def iter_action_fcurves(action):
# Legacy actions
if hasattr(action, "fcurves") and action.fcurves:
for fc in action.fcurves:
yield fc
return
# Layered actions (Blender 5+)
layers = getattr(action, "layers", None)
if not layers:
return
for layer in layers:
strips = getattr(layer, "strips", [])
for strip in strips:
channelbags = getattr(strip, "channelbags", [])
for channelbag in channelbags:
for fc in getattr(channelbag, "fcurves", []):
yield fcUse this safe action inspection pattern:
def describe_action(action):
frame_range = tuple(action.frame_range) if hasattr(action, "frame_range") else None
fcurve_count = sum(1 for _ in iter_action_fcurves(action))
return {
"name": action.name,
"legacy": bool(getattr(action, "is_action_legacy", False)),
"frame_range": frame_range,
"fcurves": fcurve_count,
}Avoid direct assumptions like:
action.fcurvesalways existsaction.groupsalways exists
Those assumptions break on layered actions and caused previous Junipali diagnostics to fail.
Target Project Conventions
- Character GLBs path:
assets/characters/*.glb - Stage GLBs path:
assets/stages/3d/*.glb - Runtime: Three.js with
GLTFLoader - Character facing: +Z forward in scene, feet aligned to ground plane at export
- World scale baseline: character height around
1.7world units in runtime after normalization
FBX / Mixamo Intake Rules
Use this sequence:
- Import FBX with animation enabled.
- Rename Mixamo bones to project names.
- Rename actions to game names (
idle,walk,attack,hurt,death, optionalrun,kick,jump,special,block). - Validate action coverage.
- Export GLB.
If user asks "can Blender do X?", check task map first and only then expand to full docs.
Project-local import pattern (from animation_tools.py):
bpy.ops.import_scene.fbx(... use_anim=True, ignore_leaf_bones=True, automatic_bone_orientation=True)
Reference-confirmed operator: bpy.ops.import_scene.fbx supports:
use_animignore_leaf_bonesautomatic_bone_orientationaxis_forward,axis_up
Project-local bone map support exists in character_rigger.py (mixamorig:* -> game names).
Required Animation Contract
Minimum required per fighter:
idlewalkattackhurtdeath
Optional but recommended:
runkickjumpspecialblock
If clips arrive with different names, normalize them using project mappings before export.
Export Rules (GLB)
Use Blender GLTF export with:
- Format:
glTF Binary (.glb) - Include:
Selected Objectswhen exporting per-asset - Transform:
+Y Up(Blender default conversion), apply transforms before export - Geometry:
Apply Modifiersenabled - Animation: enabled, include actions/NLA as needed
- Materials: keep Principled workflow compatible with GLTF
- Avoid external texture references when possible; embed via GLB
Reference-confirmed operator: bpy.ops.export_scene.gltf supports:
export_format='GLB'use_selection=Trueexport_animations=Trueexport_animation_mode='ACTIONS'export_draco_mesh_compression_enable=True(optional for stage size reduction)
Project-local pre-export sequence (from export_tools.py):
apply_all_transforms()fix_normals()pack_textures()pre_export_check()- export
Character Asset Checklist
Before handoff:
- Origin at feet center.
- Mesh and armature names are stable and clean.
- Idle clip exists and is clearly named (
Idleoridle). - Attack and movement clips use consistent names (
Walk,Jogging,Boxing,Roundhouse Kick,Drop Kick, etc). - No huge hidden helper objects inflating bounds.
- Re-export and validate by loading in browser
characters.html?view=3d. - If source is Mixamo, confirm renamed bones and action names before export.
Stage Asset Checklist
Before handoff:
- Stage mesh centered around intended play area.
- Collision-relevant floor surfaces are visually obvious.
- Heavy props are grouped and named by zone (
beach_*,chinatown_*, etc). - Lighting baked into textures only if required; runtime handles primary lights.
- Exported to
assets/stages/3d/<stage>.glb.
For quick arena blocking, use stage-builder conventions:
- 8x8 to 28x28 unit play footprints depending on stage intent.
- Explicit wall/boundary proxies or named blockers.
- Spawn empties named
Spawn_*when possible.
Handoff Format for Agents
When delivering assets to code agents, include:
- File path(s)
- Intended role (player, enemy, boss, stage)
- Clip names detected in export
- Known limitations (no clip, high poly count, missing textures)
Troubleshooting
If a model appears tiny, off-screen, or fails in lab:
- Check mesh-only bounds in Blender (hidden helpers can break fit)
- Apply transforms (
Ctrl+A) before export - Ensure armature and mesh are both exported
- Confirm file opens directly in browser URL under local server
If animations do not play:
- Ensure actions are pushed to NLA or marked for export
- Ensure keyframes exist on exported bones
- Verify clip names and duration are non-zero
If movement works in test scene but not in game runtime:
- Check for root-motion translation tracks in clips (
*.positionon root tracks). - If needed, strip translation tracks in runtime or re-export clips without baked root translation.
Practical Command Pattern
For batch or repeatable work, prefer Blender headless scripts:
/Applications/Blender.app/Contents/MacOS/Blender -b --factory-startup --python <script.py>
Use this for:
- FBX to GLB conversion batches
- action renaming passes
- stage export normalization
Collaboration Note
This skill is for asset pipeline consistency; gameplay logic remains in:
src/core/Game.jssrc/fallback/arcadeFallback.jssrc/fighters/Fighter.js