Skip to main content
Euca’s animation system (euca-animation) attaches an animator to an entity: it plays a clip by index, blends between states with an AnimStateMachine, or overlays a one-shot MontagePlayer. Clips themselves come from glTF files loaded into an AnimationLibrary. The pose model — animators, state machines, montages — is headless and mutates entities synchronously; what needs a host are the two inputs: a real glTF file to load clips from, and the AnimationLibrary resource to store them in. This page walks the model end to end; every command is real and runnable against a local server, with output captured from one.

Load a clip — and meet two gates

/animation/load reads a glTF file and adds its clips and skeleton to the AnimationLibrary. There are two gates, in order. First, the file must exist — the minimal server has no character assets, so a typical path fails at load:
Second — even with a valid file — the clips need somewhere to land: the AnimationLibrary resource. The minimal server installs only events and the rules system, so the store step returns {"ok":false,"error":"AnimationLibrary resource not initialized"}, and the clip list stays empty:
On a host that ships a rigged .glb and registers an AnimationLibrary, the same load returns {"ok":true,"meshes":1,"skeleton":true,"animations":["idle","run"]}, and /animation/list enumerates each clip’s index, name, duration, and channel count.

Play, blend, and overlay on an entity

The animator side is pure component logic — it doesn’t need the library to attach, so it works on the bare server against any spawned entity. Spawn one:
Play a clip by index. clip is a numeric index into the library (default 0), with speed and loop. The animator is attached immediately:
Attach a state machine. Named states each map to a clip index; the engine crossfades between them:
Overlay a montage. A one-shot blended overlay with blend-in/out ramps (and an optional bone mask):
Stop. Pauses the entity’s animator:
A missing target on any of these returns {"ok":false,"message":"Entity 999 not found"}.

Behavior and gotchas

The things you only find out by running it:
  • Loading has two distinct failure modes. A missing/bad path fails at the glTF read (No such file or directory); a valid file with no AnimationLibrary registered fails at the store (AnimationLibrary resource not initialized). The clip list is empty in both cases — they are not the same gate.
  • clip is a numeric index, not a clip name. /animation/play, the state-machine states, and the montage all reference clips by their integer position in the library, not by string. Index 0 is the default for play.
  • Attaching an animator needs only an entity, not the library. play, state-machine, montage, and stop all succeed on the bare server (they insert components on an entity) — the clip they point at simply doesn’t resolve to pose data until a real library is loaded and a render host skins it.
  • No /step to attach. The component is inserted on the call; the per-tick animation_evaluate pipeline (state machine → sample → crossfade → montage → root motion) runs when the host steps and renders.
  • montage is idempotent on re-trigger. A second montage on an entity that already has a MontagePlayer re-plays into the existing player rather than stacking a new one.

Endpoints

Status

  • Shipped & headless — the animator, state-machine, and montage component model (all verified on the bare server), plus crossfade blending, blend spaces, two-bone and FABRIK IK, look-at constraints, root motion, and animation events.
  • Host-dependent — clip loading needs both a real glTF file and a registered AnimationLibrary; the minimal example server has neither, so /animation/load fails and /animation/list is empty. Producing the on-screen skinned mesh from the evaluated BoneTransforms is the render host’s job.
  • Render caveat — skinned characters currently receive shadows but do not cast them: the shadow depth pass draws only the static cascade batches, so a posed skinned mesh isn’t written into the shadow map. Proper skinned shadow casting needs GPU compute skinning and is not yet wired.

Animation endpoints

Load, play, state-machine, and montage endpoints, with request and response schemas.