AMotion / Accelerated Accelerated · 12 modules

AshForge Motion · the whole tool, one course

The curve you drew is on screen.
It is not in the file.

Motion authors animation clips as tracks of keys. Most of it behaves exactly as you would expect — and one part does not, in a way that is invisible until something downstream reads the file and finds nothing.

Application  AshForge Motion Prerequisites  none Format  one course, 12 modules Time  ~75 min

What it is

A clip is tracks; a track is keys; a key is a value at a time. That is the whole model.

Modules 1–4 are the model, 5–8 are interpolation and its limits, 9–12 are where clips come from and how they ship.

The one that costs you

Curve shape is a screen-only concept. The file carries the contract you actually have, and it is smaller than what the editor shows.

Modules 5–8. Read them before you spend an afternoon shaping curves.

Why this is one course

Motion is a focused tool. Its content is 12 things worth knowing, not three escalating tiers — the old split implied the later material needed the earlier, and it does not. Read straight through, or jump to the module that matches your problem.

01

The three nouns

Clip, track, key

Read three defaults

The whole model is three nested things, and their defaults are worth memorising because you will meet them constantly.

ThingHoldsDefault
ClipA name, a duration and tracks.2.0 seconds, no tracks
TrackA name, a type, and keyframes.Track, typed Position
KeyframeA time, three numbers, an interpolation.Linear

A key always carries three numbers, whatever the track is for. Position uses all three as X, Y and Z. Rotation uses them as euler angles in degrees. Scale uses them as factors. And a Float track — a single scalar, like an opacity or a blend weight — uses only the first, carrying two unused numbers alongside it.

That is worth knowing mainly so the other two do not confuse you when you read a file: on a Float track, Y and Z are noise.

Key
There are four track types — Position, Rotation, Scale, Float — and the type is a property of the track, not of the key. Every key on a track means the same kind of thing.
02

Routing

The name is an address

Do before the slash

A track's name is not a label for your benefit. It is parsed: everything before the first slash is a bone name, and that is how a clip finds the part of the rig it is supposed to move.

Track nameBone it addressesNote
Hips/PositionHipsThe intended form.
Spine/RotationSpineThe half after the slash is not read.
Head/Something/ElseHeadOnly the first slash counts.
Track (the default)Track on export, Hips in previewThe two disagree.

The last row is the trap. With no slash there is no bone name to take, and the two code paths resolve that differently: the preview substitutes the rig's hips so that something moves and you can see your curve, while the export writes the name out verbatim as the bone.

Both behaviours are reasonable on their own. Together they mean an unrenamed track animates the hips on your screen and ships addressed to a bone that probably does not exist. Nothing warns, at either end.

"Hips/Position" — a slash, so both agree Hips/Position preview → export  → Hips "Track" — no slash, and the two part company Track preview → export  → Hips Track what you watched is not what you shipped

Figure 01 — one name, two answers Give every track a slash and the ambiguity disappears entirely.

The habit
Always name a track Bone/Property. It costs nothing, it makes the two paths agree, and it is the only form where what you preview is what you export.
03

The other half

The type is the instruction

Diagnose decoration vs data

If the bone comes from before the slash, what does the part after the slash do? Nothing. It is decoration, for you to read.

What a track actually does is decided by its Type dropdown, and the two are never cross-checked. A track named Hips/Rotation but typed Position exports as a position track carrying three position numbers — verified — and the name sits there saying otherwise.

This is a comfortable mistake to make: you rename a track to describe what you want, without changing the dropdown that decides it. The clip then moves the right bone in the wrong way, and the name in the timeline reassures you every time you look at it.

When something animates wrong
Check the Type before you check your numbers. The name in the list is the one piece of the track that has no effect on the result, and it is the piece you read.
04

On disk

What reaches the file

Read three floats, or four

Export a clip and open the file. It is small, flat and readable, and two details are worth pointing out.

Track typeNumbers per keyMeaning
Position, Scale, Float3The values as you authored them.
Rotation4A quaternion, converted from your euler degrees.

Rotation is resolved at export. You author euler degrees, and the file carries a quaternion — four floats — so whatever reads it applies them directly and does no euler-order guessing. A 90° yaw comes out with y = 0.7071, as it should.

That matters because euler angles only mean something alongside an order, and this one is fixed: X, then Y, then Z. Resolving it at the boundary means the order is Motion's problem and never the game's.

Two conveniences
Keys are sorted by time on the way out however you added them, so the file is always in order. And the export overwrites rather than adding a timestamped copy — one file per mod, always the latest, nothing to tidy up.
SymptomWhat it meansFix
Preview animates the hips, game animates nothingThe track has no slash, so the two paths disagreed. Rename it Bone/Property.
The right bone moves the wrong wayThe Type does not match what the name claims. Fix the Type; the name has no effect.
A Float track's numbers look oddOnly the first of the three is used. Ignore Y and Z; they are unused.
Rotation values in the file look unfamiliarThey are quaternions, not the degrees you typed. Expected — four floats, converted at export.
05

The choice

Two curves

Read and only two

Every keyframe carries an interpolation, and there are exactly two values it can take. New keys are Linear.

SettingBetween two keysReads as
Linear (default)A straight line at constant speed. Mechanical. Right for machinery, doors, rigid objects.
CubicA smooth curve that eases through the key. Weighted. Right for anything with mass or muscle.

The setting is genuine authoring data, and it is worth saying so before the rest of this page: it saves to the project file and comes back unchanged on reload — verified by saving an all-Cubic clip, reloading it, and finding every key still Cubic.

So it is not decorative. It is a real property of your keys, correctly stored. The question the rest of this page answers is who reads it.

Spotting it
The curve editor draws a ring around every cubic key. With interpolation behaving three different ways in three places, that ring is the only direct view of what you actually set.
06

The preview

On screen: all or nothing

Read the source per track

The setting is per key. The playback engine underneath is not: it holds one interpolation per track. Something has to give, and what gives is your per-key choice.

bool anyCubic = tr.Keyframes.Any(k => k.Interp == Interpolation.Cubic);
anim.TrackSetInterpolationType(tIdx, anyCubic ? Cubic : Linear);

One cubic key anywhere on a track makes every key on that track cubic in the preview. Twenty linear keys and one cubic one is a fully cubic track, and there is no combination of settings that produces a track which is cubic in one place and linear in another.

A per-key transition hint is passed alongside each key — a value of 0.5 for cubic keys against 1.0 for linear ones — which softens the result slightly but does not restore the distinction. The track-level choice is what governs the shape.

How this was established
Unlike everything else on this page, this one is read from the tool's source rather than measured — exercising it needs a live rig and a running animation player, which the harness for this page deliberately does not build. The two lines above are the mechanism, quoted directly.
So in practice
Treat interpolation as a track-level decision when you are judging the preview. If you want part of a move to be linear and part of it curved, split it into two tracks — that is the only way the distinction survives on screen.
07

The export

In the file: nothing

Verify identical bytes

Export the same clip twice — once with every key Linear, once with every key Cubic — and compare the two files.

ClipExported file
Three keys, all Linearidentical
Three keys, all Cubicidentical
Three keys, one Cubic among Linearidentical

Byte for byte the same. The exported key format has a time and a list of values and no field for a curve at all, so there is nowhere for the setting to be written even in principle. The file does not mention interpolation, cubic or linear anywhere.

Which produces the exact inversion this page is named for. That one cubic key is the most powerful setting on the track in the preview and the least powerful in the file — it changes everything on screen and nothing at all in what you ship.

the project file L   C   L stored exactly as set survives save + reload the preview C   C   C one cubic key wins the whole track becomes cubic the export —   —   — no curve field exists all three export identically The same three keys, read three ways. Only the leftmost is what you authored. Measured: all-Linear and all-Cubic exports were the same length and the same bytes.

Figure 01 — one setting, three readings Stored faithfully, played coarsely, shipped not at all.

08

What you can rely on

The contract you do have

Apply five fields

If the curve does not travel, it is worth being precise about what does. The exported animation carries exactly five things.

clip     Name, Duration
track    Bone, Type
key      Time, values

That is the whole contract. Everything the game does with your animation is built from times and values on a named bone — which means the way to control the feel of a move is to control the keys themselves, not the curve between them.

Concretely: if you want a movement to ease, put the easing in your key timing and spacing. Keys bunched near the end of a move produce a deceleration that survives export, because it is made of times and values. A cubic setting produces a deceleration that does not.

The technique
This is how animation was done before interpolation settings existed, and it is portable to any consumer: more keys where you want detail, spacing that carries the timing. It costs a few more keys and it is the only version of your intent that reaches the game.
SymptomWhat it meansFix
Setting one key to Cubic changed the whole trackThe preview holds one interpolation per track. Split into two tracks if you need both.
The game's animation feels different from the previewInterpolation was never exported. Express the timing in key spacing instead.
Cubic seems to do nothing in the gameCorrect — it is not in the file. Nothing to fix; use more keys.
A colleague's cubic keys came back intactThe project file stores it faithfully. Expected — authoring data is preserved.
09

Assembly

Where clips come from

Read two passes

Opening a mod runs two passes in order, and the second can overwrite the first.

PassSourceContributes
Firstassets/assets.index.json One clip per entry typed animation, or ending .glb / .gltf. Name and paths only.
Secondanimations/*.motion.json Whole clips, complete with tracks and keys.

The index pass is deliberately generous about what counts as an animation: an entry is taken if its type says animation or if its output filename ends in a glTF extension. Other asset types are ignored entirely — a texture in the same index contributes nothing, verified.

So the clip list you see on opening a mod is Refinery's inventory of animation files, with your own work laid over the top of it.

Key
You did not create most of the clips in the list. They appeared because Refinery processed a file, and they will keep appearing as long as that entry is in the index, whether or not you ever animate anything in them.
10

The placeholder

The stub, and what it ships

Diagnose two seconds of nothing

An indexed clip carries a name, a source path and an output path. That is all. Two things it does not carry are worth being exact about.

PropertyWhat you getWhat you might expect
DurationAlways 2.0The glTF animation's real length
TracksNoneThe bones the glTF animates
Name, pathsCorrect

The glTF is never parsed for its animation during this pass. Its duration is not read, its bones are not read, and the 2.0 is a constant that has nothing to do with the file. The tool's own source calls it a stub.

That would be harmless if such a clip could not leave the tool. It can. Exporting a project of nothing but stubs produces a runtime file with a named clip and an empty track list — verified — so the game receives a two-second animation that animates nothing, and nothing anywhere between the index and the file says so.

index entry Walk · models/Walk.glb clip "Walk" Duration 2.0 · 0 tracks exported clip "Tracks": [ ] The glTF is never opened for its animation, so neither the real duration nor its bones ever enter the project. The 2.0 is a constant. Measured: a stub-only project exported a clip named Walk with an empty track array.

Figure 01 — a reference, exported as an animation The track count is the only thing that distinguishes this from real work.

The check
Before exporting, look at the track count of every clip. Zero tracks means a placeholder that will ship as a silent animation. It is the one number that separates the two kinds of clip, and nothing else in the list distinguishes them.
11

The join

Replace, not merge

Do names must match

Author a clip with the same name as an indexed one and it takes its place entirely. Not merges with it — takes its place.

Authored clip's nameResultClips in the project
Matches the index entryReplaces it outright1 — yours, with tracks
Differs by anythingAdds a second clip2 — yours, and the stub

Because it is a replacement rather than a merge, the index's paths do not survive the override — verified: an authored clip that replaced an indexed one had an empty output path afterwards. Your file is the whole truth about that clip.

The second row is the trap. Rename an authored clip — to Walk_v2, say, while iterating — and the join by name silently breaks. You now have your real animation and the two-second placeholder it was meant to replace, both in the list, both exporting.

And when your file is broken
A .motion.json that fails to parse is skipped with a log warning, and the load succeeds — leaving the indexed stub standing in its place. On screen that is a clip with the right name and no animation in it, which looks exactly like a clip you have not got round to yet. If a clip you know you authored has no tracks, check the log.
12

The habit

The order that works

Ship four steps
Before you hand it over

Clip list to game data

  1. Name authored clips exactly as the index names them. the join is the name, and a mismatch ships the placeholder alongside your work
  2. Give every track a Bone/Property name. a track with no slash previews on the hips and exports elsewhere — tier one
  3. Put the feel into key timing and spacing, not interpolation. the curve is not in the exported file at all — tier two
  4. Check every clip's track count, then export. zero tracks is a placeholder that ships as a silent animation
Where this actually goes

Motion's route into the game exists and is entirely data — but this file is not yet on it.

Everything an animated creature needs is authorable: a RigRendererProps naming a prefab, a material and an anim tree, and an AnimTreeDec that is nothing but resource paths and float timings. Because those are paths, the asset bridge can serve a mod's own rigged model. The real cost is having a genuinely rigged model and knowing its bone names — demanding authoring work, not a missing mechanism.

⚠ What is missing is the plumbing at this end: the runtime export lands in the tool's own output folder, which nothing scans. Echo, Catalyst, Equilibrium and Chronicles now write a bundle inside the mod, where discovery looks; wiring Motion the same way is the outstanding step. See ashforge_shared/docs/TOOL_ROUTES_TRIAGE.md.

SymptomWhat it meansFix
A clip is in the list that you never madeRefinery indexed an animation file. Expected. Author over it using the same name.
Every imported clip is 2 secondsThe duration is a stub; the glTF is not parsed. Set the real duration when you author it.
Two clips, one real and one emptyThe authored name stopped matching the index. Rename yours back to the index's name.
A clip you authored has no tracksIts file failed to parse and was skipped. Check the log; the stub is standing in.
The game plays a clip that does nothingA placeholder was exported. Track count zero — author it or remove the index entry.

Course complete

What you now know

Check yourself

  • A clip defaults to 2 seconds; a new track is called Track, typed Position; a new key is Linear.
  • Every key carries three numbers, and a Float track uses only the first.
  • The name before the first slash is a bone address, and only the first slash counts.
  • The part after the slash is decoration — the Type dropdown decides what the track does, and the two are never cross-checked.
  • A track with no slash resolves differently in preview and export — hips versus the whole name — so always name tracks Bone/Property.
  • Rotation exports as a quaternion, four floats, converted from euler degrees in a fixed X-Y-Z order.
  • Keys are sorted by time on export, and the export overwrites rather than accumulating.
  • There are exactly two interpolations, Linear and Cubic, and new keys are Linear.
  • The setting is real authoring data — it saves and reloads per key, unchanged.
  • In the preview it is per track, not per key. One cubic key makes the whole track cubic; a per-key transition hint softens but does not restore the difference.
  • To mix curves on screen, split the move across two tracks.
  • The runtime export carries no interpolation at all. All-Linear, all-Cubic and mixed clips export byte-identical files.
  • The exported contract is five fields: clip Name and Duration, track Bone and Type, key Time and values.
  • Because of that, timing and key spacing are the only feel that reaches the game.
  • A project is assembled from two sources: Refinery's asset index, then authored .motion.json files.
  • The index contributes a clip for every animation entry or glTF file — name and paths only.
  • An indexed clip's duration is a hard-coded 2.0 and it has no tracks. The glTF is never parsed for its animation.
  • A stub exports as a named clip with an empty track list, so the game gets an animation that does nothing, silently.
  • Authored clips are matched by name, and a match replaces rather than merges — the index's paths do not survive.
  • A renamed authored clip stops overriding, leaving you shipping both the real animation and the placeholder.
  • A malformed authored file is skipped with a warning and the stub stands in for it.
  • Track count is the one number that separates real work from a placeholder.

That is Motion. Its clips reach the game through an animation tree and the asset bridge — demanding, because it needs a genuinely rigged model and its bone names, but not blocked.