Docs: Bevy guide — animation/visual deep-dive (graph add-nodes/masks, readable bone poses, volumetrics) + M1 becomes explicit rig/look proof gate

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-28 13:51:37 -07:00
parent f60e9ab60a
commit 6923888905
@@ -240,6 +240,7 @@ The most valuable existing work, and the cheapest to port — it is tick-indexed
The one area that gets *harder*, plus one that gets much easier. The one area that gets *harder*, plus one that gets much easier.
- **Pipeline:** Blender → **glTF** (Bevy's native format; Blender's best-supported export — the FBX/Humanoid/`CreateFromThisModel` gauntlet disappears). Clips load by name from the glTF; `AnimationGraph` + transitions replace the AnimatorController. - **Pipeline:** Blender → **glTF** (Bevy's native format; Blender's best-supported export — the FBX/Humanoid/`CreateFromThisModel` gauntlet disappears). Clips load by name from the glTF; `AnimationGraph` + transitions replace the AnimatorController.
- **Graph capabilities (verified vs 0.18):** the built-in `AnimationGraph` is a DAG of clip / blend / **add** nodes with per-node weights and **bone-mask groups** — velocity-driven locomotion blending, per-state playback speeds (the 1.0/0.85/0.88 retimes port), the additive hurt-flinch layer (open follow-up item — *first-class here*), and partial-body overlays with explicit mask semantics (vs the Rukhanka un-keyed-bone collapse trap). State machines via `AnimationTransitions` or `bevy_animation_graph` (which also ships a visual graph editor). Bone entities carry real deformed-pose `Transform`s and clips are inspectable data — stride footsteps, grip-anchor verification, and `TuningAuditTools`-style contact-truth audits become queryable test assertions (the Rukhanka bind-AABB readback lie has no equivalent). Still absent: built-in IK (currently unused) and root motion (already off — CC owns the transform).
- **The loss — no Humanoid retargeting.** Unity's muscle retarget let one clip library serve every rig; Bevy clips are per-skeleton. Mitigations, in order: (1) **small rig roster** — player frame + a handful of enemy skeletons, a real constraint to hold; (2) **Blender-side retarget-and-bake automation** — the existing Blender MCP scripting ([[blender-mcp-and-unity-mcp-v10]]) becomes a batch script: shared action library → apply per rig → bake → per-rig glTF. The clip *library* stays single-source; the bake fans out mechanically. - **The loss — no Humanoid retargeting.** Unity's muscle retarget let one clip library serve every rig; Bevy clips are per-skeleton. Mitigations, in order: (1) **small rig roster** — player frame + a handful of enemy skeletons, a real constraint to hold; (2) **Blender-side retarget-and-bake automation** — the existing Blender MCP scripting ([[blender-mcp-and-unity-mcp-v10]]) becomes a batch script: shared action library → apply per rig → bake → per-rig glTF. The clip *library* stays single-source; the bake fans out mechanically.
- **The win — attachments are trivial.** Bevy skeleton bones are plain entities: the salvage axe is a child entity of the hand-bone entity with a local offset. The entire 07-16 graft recipe — rigid-skinning, bindpose rebasing, scale-stripping, tangent recalculation — is replaced by `commands.entity(hand_bone).add_child(axe)`. The grip-anchor tuning flow survives as a bone-local offset in RON. - **The win — attachments are trivial.** Bevy skeleton bones are plain entities: the salvage axe is a child entity of the hand-bone entity with a local offset. The entire 07-16 graft recipe — rigid-skinning, bindpose rebasing, scale-stripping, tangent recalculation — is replaced by `commands.entity(hand_bone).add_child(axe)`. The grip-anchor tuning flow survives as a bone-local offset in RON.
- **Client-derived animation ports as-is:** a client-only Update system reads replicated state (velocity from transform deltas for interpolated entities, combat state bytes) and drives graph parameters — `PlayerAnimationDriveSystem` / `EnemyAnimationDriveSystem`, same shape, no replication. Hit reacts keep the windup-honesty gate (light react only when not mid-attack) and the poise threshold. - **Client-derived animation ports as-is:** a client-only Update system reads replicated state (velocity from transform deltas for interpolated entities, combat state bytes) and drives graph parameters — `PlayerAnimationDriveSystem` / `EnemyAnimationDriveSystem`, same shape, no replication. Hit reacts keep the windup-honesty gate (light react only when not mid-attack) and the poise threshold.
@@ -291,7 +292,7 @@ This is where the stack pays for itself; roughly five ★-class Unity limitation
Each milestone ends at an operator gate with explicit *Changed:* / *Looking for:*. Each milestone ends at an operator gate with explicit *Changed:* / *Looking for:*.
- **M0 — the spike, doubled.** Build [[Lantern_World_Model_Spike]] *in Bevy*, in a fresh repo, Unity untouched. Scope: seed → pocket-graph → runtime colliders → light field → murk render → two clients over localhost walking pockets, light revealing territory, one melee swing with damage-at-contact + probe test. **Must-validate list:** lightyear↔Avian rollback integration (§8), input edge semantics (§5), event-vs-rollback pattern (§9), wasm build compiles. *Gate:* world-model design review (already owed) **plus** the engine verdict — the spike answers both questions for one price. If either fails, the loss is one spike and the design learnings transfer back to Unity. - **M0 — the spike, doubled.** Build [[Lantern_World_Model_Spike]] *in Bevy*, in a fresh repo, Unity untouched. Scope: seed → pocket-graph → runtime colliders → light field → murk render → two clients over localhost walking pockets, light revealing territory, one melee swing with damage-at-contact + probe test. **Must-validate list:** lightyear↔Avian rollback integration (§8), input edge semantics (§5), event-vs-rollback pattern (§9), wasm build compiles. *Gate:* world-model design review (already owed) **plus** the engine verdict — the spike answers both questions for one price. If either fails, the loss is one spike and the design learnings transfer back to Unity.
- **M1 — combat-feel parity.** Target dummy, three-swing cadence + finisher, hit reacts, feel profiles, probe tests asserting §1.1 numbers. *Gate:* operator eyes-on — does the locked feel survive translation? - **M1 — combat-feel parity + rig/look proof.** The fork's weakest leg (animation/visuals) gets judged here, early and explicitly. Scope: Bathynaut rig ported (Blender→glTF, per-rig clip bake), three-swing cadence + finisher on the *real* rig, axe as bone-child attachment, hit reacts, target dummy, feel profiles, probe tests asserting §1.1 numbers — staged in a murk vignette with **volumetric god-rays** from the lantern (0.14+ volumetric fog / 0.18 scattering media). *Gate:* operator eyes-on — does the swing feel identical, and does the frame read as LANTERN? A fail here kills the fork at spike cost.
- **M2 — enemies + waves + territory.** Enemy kinds on the drive-by-derived-state pattern, wave direction, light-field-driven aggression, pocket rooms/interest management. - **M2 — enemies + waves + territory.** Enemy kinds on the drive-by-derived-state pattern, wave direction, light-field-driven aggression, pocket rooms/interest management.
- **M3 — sockets, sparks, mutations.** Content-as-RON, ability archetypes on the resolve-aim model, gauntlet-sim balance harness. - **M3 — sockets, sparks, mutations.** Content-as-RON, ability archetypes on the resolve-aim model, gauntlet-sim balance harness.
- **M4 — co-op hardening + reach.** Join-mid-run, disconnect/rejoin, dedicated-server deploy, wasm playtest build shared as a link. - **M4 — co-op hardening + reach.** Join-mid-run, disconnect/rejoin, dedicated-server deploy, wasm playtest build shared as a link.
@@ -308,6 +309,7 @@ Each milestone ends at an operator gate with explicit *Changed:* / *Looking for:
| **Avian↔lightyear rollback integration** version coupling | High (localized) | first item on the M0 must-validate list; physics facade (§8) bounds the blast radius | | **Avian↔lightyear rollback integration** version coupling | High (localized) | first item on the M0 must-validate list; physics facade (§8) bounds the blast radius |
| **No editor for the operator** — eyes-on art/feel loop degrades | High (workflow) | budgeted egui/staging/seed-gallery tooling (§13); screenshot gates; accept this is the biggest real cost of the switch | | **No editor for the operator** — eyes-on art/feel loop degrades | High (workflow) | budgeted egui/staging/seed-gallery tooling (§13); screenshot gates; accept this is the biggest real cost of the switch |
| **No animation retargeting** | Medium | small rig roster + Blender batch retarget-bake automation (§10) | | **No animation retargeting** | Medium | small rig roster + Blender batch retarget-bake automation (§10) |
| **Polish is primitives-not-defaults** (renderer/anim give capable building blocks; nothing looks good unwired) | Medium | M1 rig/look proof gate front-loads the judgment; the LANTERN look is shader/atmosphere-driven, which is the favorable case |
| **New scar set** (borrow checker in system params, WGSL debugging, rollback-event traps) | Medium | it replaces a *larger* documented scar set; start the new gotcha ledger at M0, day one | | **New scar set** (borrow checker in system params, WGSL debugging, rollback-event traps) | Medium | it replaces a *larger* documented scar set; start the new gotcha ledger at M0, day one |
| **Rewrite forfeits 430 green tests + shipped systems** | Accepted premise | operator explicitly not attached; §1 ports the knowledge; M0-before-commitment structure keeps the reversible option open | | **Rewrite forfeits 430 green tests + shipped systems** | Accepted premise | operator explicitly not attached; §1 ports the knowledge; M0-before-commitment structure keeps the reversible option open |
| **Rust ramp for the operator** | Low-Medium | operator's surface is RON data, egui panels, and Blender — not Rust internals; agents own the Rust | | **Rust ramp for the operator** | Low-Medium | operator's surface is RON data, egui panels, and Blender — not Rust internals; agents own the Rust |