AshForge Sequence · the whole tool, one course
Two keys, a clock,
and substitutions nothing tells you about.
Sequence authors cutscenes: keyframes on a timeline, props staged in a scene, and a render at the end. It substitutes quietly for anything it cannot find, so a scene that looks finished can be built largely from fallbacks.
What it is
A timeline. Keys hold values at times, the gaps between them are interpolated, and props populate the shot.
Modules 1–4 are keys and timing, 5–8 are staging, 9–12 are output.
The honest limit
⛔ A cutscene can never ship as data. The game reads three folders from a mod and none of them carries a timeline — Sequence's route to the game is a compiled assembly, not content.
Worth knowing before you plan a mod around it. Module 9 onward.
Sequence 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.
The model
A key and a clock
To find the camera at a moment, the tool sorts the keys by time, finds the pair the playhead sits between, and turns that into a number from 0 to 1: how far through the segment you are. Every other value follows that one number — position, rotation, field of view and shake alike.
The straight fraction of elapsed time is only the starting point. It is passed through the departing key's Ease first, and there are five to choose from.
| Ease | Curve | At the halfway point | Feels like |
|---|---|---|---|
linear | t | 0.50 | Constant speed. Mechanical. |
in | t² | 0.25 | Starts slow, arrives fast. |
out | 1 − (1−t)² | 0.75 | Starts fast, settles. |
inout (default) | smoothstep | 0.50 | Eases both ends. The safe one. |
hold | 0, always | 0.00 | Does not move at all. |
in easing is only a quarter done at the halfway point
— measured, 30.0, where linear time would give you 40. If a zoom feels like
it lands late, the ease is why, not the timing.inout without
complaint. There is no error and no visible difference from choosing it deliberately.Ownership
Which key owns what
Build two keys ten seconds apart, put the playhead at five, and change the ease on each key in turn. Only one of them moves the camera.
| Change | Camera at t=5 | Effect |
|---|---|---|
Ease in on the departing key | x = 20.31 | Real. A quarter of the way. |
Ease linear on the departing key | x = 50.00 | Real. Halfway. |
| Any ease on the arriving key | unchanged | No effect at all. |
The panel calls it ease out of this key, which is exactly right and easy to read past. A key's ease governs the segment that starts there. It says nothing about how the camera arrives at it — that was decided by the key before.
So to soften the end of a move, you change the ease on the key you are moving from,
and set it to out. Changing the destination key does nothing, which is the more
natural thing to try and the reason this comes first.
Figure 01 — the split down the middle of a segment The last key of a track is never a departing key, so its ease is dead in every segment.
Hard cuts
Two ways to cut
There are two controls that produce a held shot followed by a snap, and they sit on opposite ends of the same segment.
| Control | Lives on | What it does | Camera at t=9.9 of 10 |
|---|---|---|---|
Ease hold | the departing key | Freezes the segment at 0. | still at key A |
| Cut checkbox | the arriving key | Forces the segment to 0. | still at key A |
Both were measured on a ten-second move from x=0 to x=100: at 9.9
seconds the camera was still exactly at zero, and at 10 seconds it was at 100. A held shot, then
a single-frame snap.
They are interchangeable in effect and not in authoring. Cut is the one to reach for,
because it describes the edit the way an editor would — "cut to this shot" — and it
travels with the shot it introduces. hold is useful when you want the previous
shot to sit still for a beat and the reason belongs to that shot rather than the next one.
hold on key A does the same thing but is set two keys
away from where the change appears in the timeline.Position
The path is a curve
The camera does not travel in a straight line between two keys. Its position is a Catmull-Rom spline, which passes exactly through every key and curves between them, using the keys on either side as the shape of the curve.
With three keys at (0,0), (50,40) and (100,0), the
straight-line halfway point of the first segment would be (25, 20). Measured, the
camera was at (21.9, 22.5) — noticeably off the line, bowed by the pull of
the key that comes after.
This is what makes camera moves look filmed rather than driven, and it is also why a camera can swing wide of something you framed it against. If a move clips a wall it never should have reached, the cause is usually the key beyond the one you were watching.
| Symptom | What it means | Fix |
|---|---|---|
| Ease setting appears to do nothing | It is on the last key, or on the arriving key of the segment. | Set it on the key the move starts from. |
| Camera does not move at all in a segment | The departing key is set to hold, or the arriving key has Cut. |
Both are deliberate holds; clear whichever you did not intend. |
| A zoom lands late | FOV rides the eased curve, not the clock. | Use linear on that key, or move the key. |
| Camera clips scenery mid-move | The spline bowed toward a neighbouring key. | Adjust the neighbour, or add a key to straighten the segment. |
| Shot freezes at the end and stays | Duration runs past the last key. | Expected. Shorten Duration or add a key. |
Set dressing
Props, and the one with no mesh
A prop has a Kind, and five of the kinds are shapes: box, sphere, cylinder, capsule, plane. The sixth is different in a way worth understanding early.
| Kind | Makes a mesh? | What it is for |
|---|---|---|
| Box, Sphere, Cylinder, Capsule, Plane | Yes | Blocking out a set: walls, crates, ground planes. |
| Marker | No — none, ever | A named point. An actor's spot, a focus target, a spawn. |
| Anything unrecognised | Yes — a Box | Forward compatibility, so nothing vanishes. |
A Marker is not a small or invisible prop — it produces no geometry at all, and still produces none if you give it an asset path. It exists to be aimed at: you put one where an actor will stand, then point a camera key's look-at at it, and the shot is composed against a thing the game will never render.
The unrecognised case matters more than it looks. A scene saved by a newer version of the tool, carrying a prop kind this one has never heard of, opens as a grey box in the right place rather than dropping the prop. Your composition survives a version gap with a placeholder instead of a hole.
Assets
Kind is your fallback
Give a prop an asset path — a dec-style path like
Models/Items/Wood, written the way the game refers to its own content, with no file
extension — and it stages that asset instead of a primitive.
Unless it cannot. The base-game pack is opt-in and is off until you mount it, so on a fresh
checkout every asset path falls through. What you get is the prop's Kind, and
this is the part worth internalising: it is not a generic placeholder. A prop set to
Sphere with an asset path falls back to a sphere, verified.
Which turns Kind from dead metadata into a decision. Once you set an asset path it is easy to stop thinking about the shape underneath — but that shape is what you and everyone without the game will actually see.
Figure 01 — two questions, one mesh Neither "no" is reported anywhere; both simply take the other branch.
Diagnosis
The silent substitutions
The stage substitutes in four places. None of them log, none of them mark the object, and all of them look exactly like a deliberate choice.
| When this is missing | You silently get | How to tell |
|---|---|---|
| The game asset | The prop's Kind primitive, correctly placed. | Check whether the content pack is mounted. |
| The material set | The prop's flat colour. | Check the Vault library is on and the set still exists. |
| The environment preset | Clear Noon. | Compare the preset name against the shipped list. |
| The parcel | An empty stage. | Props still appear; only the set is absent. |
The environment one is the easiest to misread. Ask for a preset the tool does not ship — a typo, or one removed since the scene was made — and you get Clear Noon, which is also the default a brand-new cutscene starts on. A scene whose careful night lighting has quietly become midday is indistinguishable from a scene nobody set an environment on.
The material one is subtler still. A prop stores its material as the set's hash, not its name, because names in a real library are not unique — several sets share one. Storing a name would mean "the first set called this", so re-indexing the library could hand a saved scene a different material than the one it was composed with. The hash avoids that, and the cost is that a missing set gives you a flat colour with nothing readable to search for.
Places and effects
A place is not a prop
Two things on the stage are deliberately not ordinary props, and both separations pay off the moment a scene gets real.
A parcel is a whole prefab place — the shipped duplex is hundreds of placements — staged by name under its own root. It is not in the prop list, and it should not be: a few hundred rows of building parts would bury the four props you positioned by hand. Swap the parcel and your props stay exactly where they were, verified.
A VFX prop carries a time and a duration, and no other prop does. That is the whole reason effects are a separate kind rather than another asset path: a muzzle flash happens on a beat; a crate simply is. A duration of zero means it never stops emitting — right for smoke drifting through a shot, wrong for an impact.
| Symptom | What it means | Fix |
|---|---|---|
| Everything is grey shapes | The content pack is off, so every asset path fell through. | Mount it, or accept the blockout — the composition is still correct. |
| A prop is the wrong shape without the game | Its Kind was never set to match the asset. | Set Kind to the nearest primitive at the right scale. |
| A prop is invisible entirely | It is a Marker. Markers never have geometry. | Working as designed — aim a look-at at it. |
| Night scene opens at midday | The preset name is not one the tool ships. | Re-pick from the list; the fallback is always Clear Noon. |
| A prop lost its material | The library is off, or the set's hash no longer resolves. | Re-enable the library; otherwise re-pick the set. |
| An effect runs forever | Duration is 0, which means never stop. | Give it a duration. |
The two buttons
Two exports, one scene
Take one cutscene — a camera track, a lamp called KeyLight, a
prop called SignpostProp, the duplex parcel and a Clear Noon environment
— and press both export buttons. Then search each file for those names.
| In the scene | Runtime export | Bundle export |
|---|---|---|
| Tracks and keys | Present | Present |
| Lamps | Present | Absent |
| Props and markers | Present | Absent |
| Parcel | Present | Absent |
| Environment | Present | Absent |
| File size | 2648 chars | 689 chars |
The runtime export serialises the cutscene whole — it is the model, written out. The bundle is a deliberately reduced projection: name, duration, and for each track its name, type and keys. It is a timing document, and a good one, but the stage is not in it.
Neither button says so. They log the same success and hand back a path, and the smaller file is only obviously smaller if you go looking. A quarter of the size is the giveaway.
A cutscene is not content the game can load, and no export on this page changes that.
The game reads exactly three folders from a mod — Dec/,
Assembly/ and Parcels/ — and there is no cutscene, timeline or
camera definition among its 69 definition types. The nearest-sounding candidate carries a
label and a description and nothing else. So both files described above are real and useful
between tools and to your own code; neither is a route into the game.
Sequence's route is an Assembly/ — a cutscene reaches a player as
code that plays it, not as data the game reads. That is a settled verdict rather than pending
work; see ashforge_shared/docs/TOOL_ROUTES_TRIAGE.md. ⚠ Both exports also
land in the tool's own output folder, which nothing else scans.
Validation
What Validate cannot see
Validate answers one question: is this the right shape? It is worth knowing exactly what that covers, because the name promises a great deal more.
| Validate catches | Validate does not catch |
|---|---|
| A project with no cutscenes | A parcel name nothing can resolve |
| A cutscene with zero duration | An asset path that loads nothing |
| A cutscene with no tracks | A material set that no longer exists |
| A track with no keys | An ease name the tool does not recognise |
| A key at 999s in an eight-second cutscene |
That right-hand column is not hypothetical. A cutscene was built carrying every one of those five problems at once and validation returned clean — no issues, no warnings about any of them.
Which follows directly from tier two. The stage substitutes silently for everything it cannot
find, so by the time validation looks, there is nothing to find wrong: the asset already fell
back to a primitive, the preset already became Clear Noon, the ease name already became
inout. A validator downstream of a silent fallback can only ever see success.
Frames
Rendering frames
The one output you can judge with your eyes: a folder of PNGs, one per frame, rendered by stepping the playhead and posing the camera for exactly that instant.
frames = ceil(Duration × fps) 8s at 24 fps → 192 10s at 30 fps → 300 0.5s at 24 fps → 12
Note what drives the count. It is the cutscene's Duration, not the time of its last key — so the still frame you deliberately left at the end, from tier one, costs real frames and real time. If a render is taking longer than the action lasts, that is why.
The render is deterministic by design: the playhead is stepped to frame / fps
and posed there, rather than played in real time, so the result does not depend on how fast your
machine drew the previous frame. The same cutscene rendered twice gives the same frames.
The habit
The order that works
Cutscene to file
- Set the mod name. it becomes the filename of every export, and the default is not yours
- Mount the content pack and library, then watch the shot once. this is the only content check there is; validation cannot see substitutions
- Press Validate for the structural problems. it catches the empty track and the zeroed duration, which are easy to miss
- Clear the output folder, then export. exports accumulate with timestamps and nothing marks which is current
- Choose runtime unless you know the consumer supplies its own world. the bundle silently omits lamps, props, parcel and environment
| Symptom | What it means | Fix |
|---|---|---|
| The shot plays with no set | A bundle was shipped where a runtime export was needed. | Re-export as runtime. |
| Validate passes but the shot looks wrong | Working as designed — it checks shape, not content. | Mount your content and watch it; see tier two. |
| Nobody knows which export is current | Every press wrote a new timestamped file. | Clear the folder, export once, hand over one file. |
| The render is far longer than the action | Frames follow Duration, not the last key. | Shorten Duration, or accept the held tail. |
| The render refused to start | Zero duration, or a frame rate of zero or less. | The only two refusals; both are reported. |
| Exported files are named for nobody | The mod name was never set. | Set it and export again. |
Course complete
What you now know
Check yourself
- The camera at any moment comes from the pair of keys the playhead sits between, reduced to one number from 0 to 1.
- Position, rotation, field of view and shake all ride that same eased number.
- Ease belongs to the departing key — "ease out of this key" — so the last key's ease can never do anything.
- The five eases are
linear,in,out,inout(the default) andhold; an unrecognised name silently becomesinout. - Cut belongs to the arriving key, and produces the same held-then-snap as
holdon the departing one. - Outside the keyed range the camera holds the first or last shot, so extra Duration is a still frame.
- Position is a Catmull-Rom spline, shaped by four keys at a time, so paths bow and neighbours matter.
- A look-at target is only interpolated when both keys carry one.
- A cutscene owns props, lamps, a parcel and an environment, and none of them are required for it to open.
- Five prop kinds are shapes; a Marker has no mesh at all, even with an asset path.
- An unrecognised Kind becomes a Box, so a scene from a newer tool loses nothing.
- Base-game content is opt-in and off by default, so asset paths fall through until you mount it.
- Kind is the fallback shape for a prop with an asset path — a Sphere falls back to a sphere, not a generic box.
- A material set is stored as a hash, not a name, because library names are not unique; a missing one falls back to the prop's colour.
- An unknown environment preset silently becomes Clear Noon, which is also the default — the two are indistinguishable.
- A parcel is a place, not a prop; swapping it leaves hand-placed props alone.
- A VFX prop carries a start time and duration; duration 0 means it never stops.
- Runtime export serialises the cutscene whole — tracks, lamps, props, parcel and environment.
- Bundle export keeps name, duration and tracks, and silently omits the entire stage — 689 characters against the runtime's 2648 for the same scene.
- Both report success identically, so the choice is yours to get right.
- Every export is timestamped and accumulates; nothing marks which file is current.
- Validate checks shape, not content: no cutscenes, zero duration, no tracks, no keys.
- A scene with an unresolvable parcel, a dead asset path, a missing material, an invalid ease and a key past the end validates clean — because the stage already substituted for all of them.
- Frames are
ceil(Duration × fps), driven by Duration rather than the last key, and the render is deterministic. - The render refuses only on zero duration or a non-positive frame rate.
That is Sequence. ⛔ Its output is a render and a record, not shippable content — the value is in previsualising something you will then build in code.
