Animation sets V1
An .animset uses the common blitz3d.animset V1 resource envelope. Asset kind animset is public value WORLD_ASSET_KIND_ANIMSET (14). It references one model with options.animated=true; animation samples remain in that model. It shares the same dependency, inline/external, workspace, save and export services as the other resource families.
The definition contains:
{
"model": "character",
"clips": [
{
"alias": "walk", "source": "Walk", "mode": "loop",
"speed": 1, "blend": 10,
"events": [{"name": "step", "time": 0.5, "unit": "normalized"}]
}
],
"rootMotion": {"mode": "extract", "bone": "Root", "vertical": false, "yaw": true}
}
Aliases and imported source names are exact and case-sensitive. Missing or ambiguous imported names fail preparation before construction. A set has 1–256 mappings, unique aliases and unique source names. Events belong to the native sequence, so multiple aliases cannot install competing event lists on one clip. There are at most 1,024 events per clip and 4,096 per set.
mode is loop (default), ping-pong or once. speed defaults to 1, including support for zero and reverse playback. blend defaults to 0. Both use the existing CrossFadeAnim contract: speed scales animation ticks per UpdateWorld unit and blend is measured in those update units. They are not seconds. glTF imports sample at 60 ticks per second; other model formats retain their imported frame contracts. Applications commonly update by elapsed seconds multiplied by 60, as the sample does.
Every event requires a unit: frames is an imported frame value, and normalized is a fraction from 0 to 1 multiplied by the loaded sequence length. Frame events must fit the loaded clip. Seconds are intentionally not accepted because the legacy model formats do not expose one uniform source frame rate. Equal-time markers retain declaration order and use the existing traversal, loop, reverse, crossfade and bounded event-queue behavior.
Root motion defaults to none. mode=none accepts no other motion fields. extract and apply require one unambiguous animated bone name or supported hierarchy path. Horizontal motion is always included; vertical defaults false and yaw true, matching the native root-motion API. Apply moves the character; extract exposes deltas through AnimRootMotionX/Y/Z/Yaw for application policy. There is no retargeter, state machine, serialized cursor or implicit playback.
Load a resource document and prepare it with LoadResourceDocumentAsync. The resource asset then supports CreateAnimationSet(asset, parent=0), which returns an independently owned model in the selected/parent world. ApplyAnimationSet (entity, asset) binds to an existing animated entity by clip and node identity; it does not retarget animation samples or change the target's current cursor. Both operations validate all bindings before publication. Applying replaces the target's event configuration and root-motion settings atomically, clearing old queued events. Failure leaves them unchanged. AnimationSetError reports failures.
PlayAnimationSet(entity, alias, restart=0) applies the saved speed/mode/blend for that alias through the existing crossfade controller. It returns false for an unknown alias or unconfigured target without changing playback. CopyEntity retains defaults/events with an independent cursor and queue. Freeing the loader world leaves constructed instances and their immutable configuration alive.
A world model component may use an animset asset as its asset; it constructs that set's model and configuration, initially stopped. Alternatively a raw animated model component can reference animationSet. These forms are mutually exclusive. Alias rename/removal, prefab capture/expansion and typed serialization retain the binding. Structural live edits continue to require offline restart.
World Editor's right-click Animation Set action starts from the selected animated model, using its imported named clips. Imported sets have an Edit Animation Set action in Assets. The set opens as a tab beside Scene; its preview uses a separate world and explicit Play clip/Stop. Clip aliases, speed, loop mode, crossfade, event lists and root motion have ordinary controls; adding or removing clips and dependency/model changes use the tab's Source page. Save supports embedded/external scope and shared history; Save All includes new and embedded drafts as well as named external resources.
See samples/animation-sets for a complete two-character program and export plan. Portable validation does not establish native CPU/GPU playback or editor UX acceptance; those gates are tracked in the reusable-assets progress record.
For editor steps and F1 help, see the World Editor User Guide.