Skip to content
Work in progress. These docs describe Spawnite at launch, and some parts are still being built.

Animations

This page walks one clip from “I need a cast animation” to a spell that leaves the hand on the right frame. Your agent runs each step with a command or a studio tool, reads what it printed, and shows you one picture or one link when a frame is yours to judge. The page assumes your game has a <CharacterSpawn> in a VRM avatar, as Make your game sets one up, and that Models has told you what a model file must be.

A clip is a VRMA file: a motion for the humanoid skeleton every avatar shares, so one clip plays on every avatar the same way. The engine plays a clip over the character’s pose with playClip, or when an ability casts, and it raises a mark each time the clip crosses one of the seconds you gave it. Unity’s animation window and Unreal’s montage editor put a clip’s events on a timeline you scrub; Roblox’s Animation Editor does the same with its animation events. The platform has no editor window, so the same loop runs through commands and one web page, and your agent drives it.

Each of the following gives you a .vrma file in the game’s public/assets/ folder:

  • The asset library. spawnite assets list --kind clip lists every clip the platform holds, with its length and license, and the studio’s list_assets with kind: "clip" lists the same. spawnite add asset charged-spell-cast downloads one to public/assets/charged-spell-cast.vrma. The library’s idle, run, jump and land come from Mixamo; its casts come from Meshy, bought once for every game. Query by what the clip does, such as spawnite assets list cast --kind clip.
  • A character you own. A character rigged by Meshy carries its own clips. spawnite model clip rigged.glb --clip cast --folder public/assets writes the one clip as a VRMA that every avatar plays, and spawnite model avatar makes the character itself an avatar, as Models says. A rig with other bone names, such as Mixamo’s, is refused with the names it lacks.
  • A body built in Blender has no rigging tool yet. make_model exports a rig only when its script builds one, and the platform’s skeleton cannot be fitted to a new body with one command. Until it can, take a clip from the library or from a Meshy rig.

Check the license before a clip goes into a game you publish. The library prints each clip’s license, and a clip from a character you bought follows that character’s.

Before the clip plays anywhere, your agent reads what it does:

$ spawnite model check public/assets/charged-spell-cast.vrma
charged-spell-cast.vrma: 2.70 s, the arms peak at 0.50 s, where a release mark starts; spawnite play timeline settles it.
Hips: drop -0.19 m, travel 0.11 m.
leftUpperArm turns 77° at 0.50 s
leftLowerArm turns 77° at 0.57 s
rightLowerArm turns 68° at 0.70 s
…

The studio’s check_model on the same file returns the same table. The table says whether the clip is the right kind, how long it runs, and where its motion peaks: an agent picks between two casts from the table alone, and starts a release mark from the arms’ peak. The peak is a start, not the mark. On the nova above, the arms reach their largest turn from the first frame at 0.50 s, as the hands rise, and let the spell go at 1.4 s, when they stand highest before they come down; the frames settle it, as the next section says.

A clip joins a game with one line, which names it, says where its file is, and marks where things happen in it, in seconds from its start:

import { registerClip } from "@spawnite/engine";
registerClip("charged-spell-cast", "/assets/charged-spell-cast.vrma", {
marks: { release: 1.4, settle: 1.8 },
});

Register it before the first character draws, such as beside the game’s abilities. release is the mark an ability casts at:

registerAbility(world, "frost-nova", {
kind: AbilityKind.Area,
label: "Frost Nova",
clip: "charged-spell-cast",
cooldownSeconds: 12,
radius: 6,
damage: { min: 25, max: 30, stat: "spellPower" },
});

The cast time has one source: an ability with a clip releases at the clip’s release mark, and castSeconds beside it throws, as does a clip with no release mark. The error names the clip and says what to add. Any other mark is yours to name, for a look to hear in the next section but one.

Start the mark at the number the table gave, such as release: 0.5. The next section replaces it with the frame.

See the clip on the character, frame by frame

Section titled “See the clip on the character, frame by frame”

A clip is judged on the body that wears it, in the game’s own light, with the character’s own wand in her hand. spawnite play timeline shoots it there:

$ spawnite play start
$ spawnite play step --seconds 1
$ spawnite play timeline --clip charged-spell-cast --every 0.1 --seconds 2 --out .work/nova.png
Saved to .work/nova.png: 21 frames, one every 6 steps, 0.1 s of the game's time, from the play of clip "charged-spell-cast", cropped round [controlled].
Pick the frame; its second is the mark: registerClip("charged-spell-cast", url, { marks: { release: <seconds> } }), beside the url the game registered the clip with.

The sheet tiles one frame every tenth of a second with its second under it, cropped round the character. Your agent reads it, picks the frame where the hands let the spell go, and writes the second under that frame into the registerClip line, which the command prints to paste. The studio’s timeline tool with clip returns the same sheet and the same line. The director says what the sheet’s options do, such as --every 0.05 for a short clip.

A second mark, such as the frame the hands come down, is read off the same sheet.

The frame is a judgement, and the person who can make it should not need to set anything up. The model viewer scrubs the clip on an avatar with the marks drawn on its track, and a link opens it ready:

https://tools.spawnite.com/model?avatar=chifa&clip=charged-spell-cast&marks=release:1.4,settle:1.8

The link names an avatar and a clip the platform bundles, and the marks to draw. Your agent hands you the link; you drag the track to the frame you want, read the second under it, and say the number. A drag holds the frame, and Play runs the clip on from there. A clip outside the platform’s bundle is dropped on the page by hand, and ?marks= goes on it. The model viewer says what else the page shows.

The viewer writes nothing. Your agent writes the number into the registerClip line, and the ability casts at it from the next reload.

A look that plays on a mark hears it on the page that draws the clip, exact to the frame rather than to the room’s tick:

import { useClipMark } from "@spawnite/engine";
function NovaLook({ entity }: { entity: Entity }) {
const shards = useRef<ShardsHandle>(null);
useClipMark(entity, "settle", () => shards.current?.standUp());
return <Shards ref={shards} />;
}

Shards stands for the game’s own look. The hook calls heard with the clip, the mark, its seconds and the play, each time the character’s one-shot crosses the mark, on every page that draws her. A spell’s own effect needs no hook: an ability’s SpellLandedEvent and SpellStruckEvent come from the cast, which releases at release, as the abilities page says. The player page says how a clip plays over her pose, fades, and holds.

The clip is finished when all of the following hold:

  • spawnite model check on the file prints its table with no refusal.
  • The registerClip line carries every mark the game reads, each read off the sheet.
  • The ability’s clip names it, and the game starts with no error about a mark.
  • A person has opened the viewer’s link, or read the sheet, and confirmed the release frame.
  • spawnite play timeline <control>, with the key the ability sits on, shows the cast with its effect on the frame the mark names. The --clip sheet plays the clip alone, with no cast, so it cannot show the effect.