5.1 KiB
Animation Authoring
Blacksite's first production animation path supports skinned glTF 2.0 models (.gltf and .glb).
It normalizes imported rig and clip metadata into generated manifests, keeps authored scene data
independent of Bevy's runtime graph/player components, and uses the same controller contract in
editor preview, PIE, and standalone builds.
Import And Placement
Place animated sources under assets/ and refresh or reimport them from the Asset Browser. The
registry writes assets/animations/generated/<asset-id>.animation.ron beside the existing static
mesh artifact. Expanding a model row shows:
- skeleton entries with joint count and signature summary;
- animation clips with duration and event count;
- mesh, material, and texture entries from the static import contract.
Skeleton rows are inspect-only. Dragging an animation clip into the viewport creates one
ImportedModel actor with a stable ModelRef and AnimationControllerDesc and selects it for
immediate inspection. When an imported-model actor is selected, the same drag assigns the clip as a
new controller state instead. Assignment is one undoable command and requires an exact
skeleton-signature match.
Skinned primitive rows are inspect-only because their vertex data requires the source skin hierarchy. Their thumbnails render the complete source scene, and drag/place actions direct authors to place the model or an animation clip instead of creating an invalid detached mesh.
Controller Inspector
The Animation Controller component exposes the selected skeleton, default crossfade, named states, default state, clip, loop, speed, and optional playback range. State IDs are gameplay keys and must be non-empty and unique; labels are presentation only. Component add, remove, reset, copy, paste, and property changes use typed editor history and participate in scene dirty tracking.
The Preview section selects a state, plays or pauses it, stops playback, and scrubs within the authored range. Preview requests use the game runtime adapter and do not change the controller, history, or scene dirty state. Entering PIE clears any paused edit-mode scrub so the authored default state can run; leaving PIE clears transient playback while retaining authored data.
Runtime API
Gameplay changes state by sending a validated request through game::animation:
game::animation::request_animation_state(
world,
game::animation::AnimationStateRequest::new(actor, "run").with_crossfade(0.15),
)?;
An omitted crossfade uses the controller default. Invalid actor or state requests return an error
and preserve current playback. If edited controller data cannot rebuild its runtime graph, the old
graph is stopped and cleared instead of continuing stale playback. AnimationGraph,
AnimationPlayer, transitions, preview state, and hydrated model roots are runtime-only and never
serialize into authored scenes.
Stable Identity And Moves
ModelRef, skeleton references, and clip references carry the model registry UUID. Generated
artifacts are keyed by that UUID; source paths are cached resolution and repair hints. When one
model is moved or renamed on disk, catalog refresh reconciles it by its animation-manifest content
hash, preserves the UUID, and regenerates both manifests with the new source path. An identical copy
is not treated as a move while the original still exists. Ambiguous content matches intentionally
receive a new identity rather than silently binding the wrong asset.
Legacy path-only ModelRef values remain readable and use their cached path. Reassign or replace a
legacy model actor to opt it into stable move resolution.
Skeleton compatibility hashes the exact Bevy 0.19 glTF node-name segments and bind poses, including whitespace and slash characters. The readable joint paths shown by the editor are deliberately not used as identity. Animation-manifest schema v1 artifacts must be reimported to generate schema v2 signatures.
Validation And Format Boundary
Interactive diagnostics and cargo validate-levels resolve registry UUIDs, generated manifests,
stable subasset IDs, source dependencies, default/state IDs, playback ranges, speeds, crossfades,
runtime format support, exact source-content fingerprints, and exact rig compatibility. Findings
identify the owning actor and controller property and include a repair action. Packaging includes
the same source files and generated artifacts checked by validation.
FBX remains supported for static model import only. An FBX containing skin deformers or animation
stacks emits a blocking diagnostic directing the author to convert it to glTF. Animation v1 does
not support one glTF asset containing animation channels under multiple top-level roots, because
Bevy creates a separate AnimationPlayer for each root. Split those rigs into separate assets or
export them beneath one common root. Animation v1 also does not provide implicit retargeting, blend
trees, a visual state graph, root motion, IK, or motion matching.
See ADR 0031 for the persistent/runtime boundary and the working implementation plan for acceptance gates.