The development runtime now connects the existing AnimationState component to rigid and skeletal model poses. Animation phase advances at simulation boundaries and the canonical ECS presentation bridge emits the evaluated model matrices or bone palettes. This is the state integration step toward animated actors; the playable traveler art and shared animation transport are still separate work.
#Contract and binding
A renderable entity selects an immutable imported model through RenderMesh.asset. Its AnimationState is:
{ clip: 'clip:0', time: 0, speed: 1, loop: true }clip:N selects the model's zero-based clip index. The canonical decimal spelling disambiguates duplicate or empty source clip names. Clip names remain available as display metadata; the runtime never guesses a binding from a name. time is the current clip-local phase in seconds, bounded from zero through that clip's duration. speed is bounded to -8 through 8. Positive and negative rates play forward and backward, zero holds the current pose, loops wrap, and nonlooping playback clamps at its endpoints. Zero-duration clips stay at zero.
The existing declarative component schema is unchanged. Model-specific validation adds the clip reference and duration constraints. ECS commits and full checkpoint restoration reject missing models/clips, invalid phases, primitive replacements that would break an active binding, and animation of an authored static imported collider. Animated visual geometry needs a separate collision proxy. The current profile admits 32 animated entities across the complete simulation, including hidden entities and other places. Presentation's independent draw and bone-palette limits still apply.
#Advancement and projection
The animation.advance system runs in the behavior phase, after input and before physics. It stages changed phases in one ECS transaction per tick. It does not write for a stopped clip or an unchanged clamped endpoint. Pause stops simulation advancement. Clip phase never comes from converting the uint64 simulation tick to a JavaScript Number, so long-running timelines retain exact tick identity.
The presentation bridge treats AnimationState as a render dependency. An animation-only update reevaluates that entity's draws without recomposing unrelated spatial transforms. It selects the rigid or skeletal evaluator from the installed model, preserves external entity placement and material overrides, and emits the existing versioned presentation protocol. Removing the component restores the authored rest pose. Catalog creation owns all input model records before its first asynchronous validation, preventing later caller mutations from separating geometry and animation identities.
Pose evaluation can reject an admitted curve at a singular or out-of-budget sample. A failed projection preserves the last baseline, spatial cache and reader cursor; correcting the component lets the next poll resume from the last accepted scene. Simulation validates binding and phase, not universal renderability of every interpolated pose.
This increment samples at accepted simulation states. Renderer-side interpolation, blend trees, locomotion selection, root motion and attachments remain open. It does not make frame-rate-dependent advancement the authoritative clock.
#Checkpoint profile 5
darkwind.simulation.5 identifies the new advancement semantics. Complete checkpoints already serialize AnimationState through the component catalog; restoration now validates its model binding and resumes advancement from the captured phase, speed and loop flag. Native physics, entities, input, events and scheduler state continue to restore together.
Simulation.migrateCheckpoint explicitly accepts profile 4 with its original world formats 1–3. It checks the old envelope, content signature and catalog, then preserves the entire payload under profile 5. The actual profile-4 fixture was captured before this implementation from source 260f7e4; it is not a forged profile label on a newer checkpoint. Profiles 1–3 retain their existing migration routes and now produce profile 5. An old invalid or ambiguous animation binding fails migration rather than being silently activated.
Full native checkpoints are distinct from the player's lightweight format-2 local save and the relay's shared state. Those formats are unchanged and do not yet carry model animation state. Shared/reconnected actor animation needs its own transport and authority integration before playable multiplayer animation is complete.
#Verification
Headless cases cover forward/reverse looping, clamping, zero speed/duration, invalid references and times, 32/33-entity admission, pause, exact ticks above 2^53, ninety continued steps after full native restoration, independent model pose projection, rest-pose recovery, failed-pose rollback and an actual profile-4 migration. The authoring, prefab and replay evidence has new versions that explicitly name the simulation profile. Old golden fixtures are retained; tests compare all non-checkpoint content, identity and final gameplay fields against them.
The model-skeleton.2 Observatory probe adds component-driven baselines/deltas, ECS snapshot restoration and removal-to-rest. Three new GPU comparisons use independently authored static GLB references, alongside the existing nine skin/shadow comparisons. It continues to exercise actual device loss and resource disposal. This is software-WebGPU evidence, not a physical-device performance claim.
Original character assets, renderer interpolation, shared actor state, lightweight save integration, attachment APIs and the remaining full-plan requirements are not complete. The running beta is not rebuilt or deployed by this increment.
Source e24d554 passes 281 headless tests and all 26 browser scenarios, with zero maximum channel error across twelve skeletal/ECS reference frames. The record retains initial failures caused by prior-profile golden checkpoint hashes and the explicit fixture version changes. Prior skeletal CI records separate repeated-run budget and delayed player presentation failures; local acceptance does not establish a fix for the latter.
#Authorable animation trees (F13)
World format 71 adds an optional animationTree on imported visual objects.
Editor → Animation trees opens the saved actor picker, state map, clip catalog,
parameter rehearsal and reusable definition. Stage it, Save changes and publish
a playtest through the normal editor flow. Keep physical collision in a separate
proxy; animated triangle colliders and rigid-body skins remain separate profiles.
animation-tree.1 defines up to 16 named states, 16 numeric parameters and 64
ordered transitions. States contain a clip or a one-dimensional blend with up to
eight increasing thresholds. Only neighbouring clips contribute. Conditions use
gt/gte/lt/lte/eq/neq, an elapsed-state minimum and a 0–5 second crossfade.
Parameters can use shared flag:name, door:name or NPC speed, or be supplied
by place-authority ECS code through engine.AnimationTreeState. State phase,
parameters, transition and weighted samples are a public session component, so
the existing generic ECS replication/checkpoint binding carries them. Both rigid
and skeletal imported renderers evaluate the same maximum four contributing poses.
Ordinary room clients resolve the replicated flags/doors locally; clip phase is
presentation state and is not an additional room SQL ledger or gameplay authority.
Local authored progress saves retain tree state and exact native checkpoints retain
the component catalog/state. Existing single-clip worlds retain their contracts.
Focused delivery check: tests/animation-trees.test.ts passes one imported
skinned-actor journey covering saved definition/undo, shared-source transitions,
blend rendering, local save restore and exact checkpoint continuation. Type,
package boundary and wire checks pass. The actual authoring dialog was visually
reviewed; milestone screenshot.
After feature completion: broader asset/transition matrices, interrupted fades, late-join presentation phase alignment, network/device review and final visual polish. These do not reopen the feature inventory.