Animation
The framework plays montages when you have them and interpolates when you do not. Both paths reach the same states through the same events, so you can start with the second and move to the first without changing any code.
The procedural transition
With no animation set, or no montage matching the transition, the rider slides from the entry point to the seat: eased with a smoothstep, arced so the path does not go through the door frame, and computed in the seat's own frame — so the whole thing stays correct on a vehicle that is moving.
That last part is why the rider attaches at the start of a procedural get-in rather than at the end. The slide is a relative offset shrinking to zero; the car's motion is carried by the attachment, not fought by it.
| Setting | Default | |
|---|---|---|
| Duration | 0.55 s | |
| Arc Height | 25 cm | Zero is a straight line through the door frame. |
| Easing Curve | none | A 0..1 curve. Without one, a smoothstep. |
| Interpolate Rotation | true | Turn to face the seat over the same window. |
This is not a consolation prize. For a prototype, a debug build, or a mount nobody has authored animations for, it reads as intentional — and it is what makes the framework testable with no content at all.
Animation sets
Create one — Content Browser → Miscellaneous → Data Asset → ED Mount Animation Set — and point your rider component at it.
Each entry matches on:
| Field | Empty means | |
|---|---|---|
| Phase Tag | never matches | Mount.Phase.Enter, .Exit, .Shuffle, .Seated. Required. |
| Entry Tags | any side | Mount.Entry.Left and friends. |
| Role Tags | any role | Mount.Role.Driver, or your own. |
| Context Query | always passes | A query against the rider's tags, the mount's, and the request's. |
and carries:
| Field | Default | |
|---|---|---|
| Animation | — | A montage, or a plain sequence. Soft, and preloaded when the mount spawns. |
| Start Section | none | Montages only. |
| Play Rate | 1.0 | |
| Use Motion Warping | true | Off for a montage authored in place. |
| Attach Fraction | 0.55 | When the rider attaches — only when the montage has no attach notify. |
| Priority | 0 | Breaks ties between equally specific entries. |
A montage or a sequence
Either. A sequence is played into the slot as a dynamic montage, which is the same thing without the asset — so reach for a real montage when you want its sections or its notifies, and a sequence when you have neither. A get-in usually wants a montage. A seated pose never does.
How one gets chosen
Every entry whose conditions pass is scored on how specific it is: +8 for naming a side, +4 for a role, +2 for a context query. Highest wins; ties go to Priority, then to declaration order.
So fill the array in with one catch-all per phase first, then override what deserves it:
0 Mount.Phase.Enter AM_GetIn_Generic
1 Mount.Phase.Enter + Mount.Entry.Left AM_GetIn_LeftDoor
2 Mount.Phase.Enter + Mount.Entry.Right AM_GetIn_RightDoor
3 Mount.Phase.Enter + Mount.Entry.Left + Driver AM_GetIn_LeftDoor_Driver
4 Mount.Phase.Exit AM_GetOut_Generic
5 Mount.Phase.Shuffle AM_ShuffleAcross
A left-door driver gets 3. A left-door passenger gets 1. A rear-door anyone gets 0. Nothing is ever silently unhandled: a phase with no match falls to the procedural slide.
Which set is used
Most specific wins: the seat's override, then the mount's, then the rider's, then the project default.
Key sets on the character, not the vehicle. A game has a handful of ways of climbing into things and a great many things to climb into, so keying on the rider and overriding on the mount is far less duplication than the reverse.
Notifies
One notify class, ED Mount Event, carrying a gameplay tag. Put it on the frame the thing actually
happens.
| Tag | What the framework does |
|---|---|
Mount.Event.Attach | Attaches the rider. On the server, takes the seat. |
Mount.Event.Detach | Detaches, places the rider at the exit. On the server, frees the seat. |
Mount.Event.Finished | Ends the transition early. Optional. |
Mount.Event.DoorOpen / .DoorClose | Calls SetSeatDoorOpen on the mount. |
| anything else | Broadcast on OnMountEvent, on the rider and the mount. Yours. |
ED Mount Event Window is the same idea with a duration: one tag when it opens, another when it
closes. That is what a door is — mark the window from the frame the hand reaches the handle to the
frame it lets go, and the vehicle's door follows the animation exactly, on every machine, with nothing
replicated, because every machine is playing the same montage.
Systems that ship a class per moment fix the set of moments an animator can mark at whatever the plugin author thought of, and make adding a sixth a code change. A tag makes it an afternoon.
Doors, with or without a montage
Mount.Event.DoorOpen and .DoorClose are usually a windowed notify. When the transition has no
montage — or the montage does not mark the door itself — the framework opens the door for the length of
the transition and closes it at the end.
The same rule as the attach fraction, for the same reason: an authored notify must never be second-guessed, and its absence must not mean the feature quietly does nothing. A project with no animations still gets doors that open when somebody gets in, and a transition that is interrupted closes the door it opened.
When the notify is missing
Timing falls back to Attach Fraction. The framework checks once, when the transition starts, whether the montage actually carries the notify it needs — so an authored notify at 70% is never pre-empted by a fallback at 55%, and a montage with no notify at all still seats the rider.
If the montage is cut short entirely, a watchdog completes the transition shortly past its expected end. See The state machine.
Motion warping
Add a Motion Warping component to your rider. The framework writes two targets before the montage's first evaluated frame:
| Target | Where it points |
|---|---|
EDMountEntry | The chosen entry point. |
EDMountSeat | The seat. |
In the montage, add a Motion Warping notify state over the section that should land and point it at one of those names. They are constants rather than settings so a montage authored in one project keeps working in the next — and so a mismatch is impossible rather than being an animation that plays and simply does not arrive.
Without a warping component everything still works; the montage plays as authored and the framework snaps the rider to the seat at the attach moment.
The seated pose
Mount.Phase.Seated is not a transition. An entry tagged with it plays for as long as the rider is
sitting, looping, and stops when they are not.
It is driven from the phase rather than from the request, which is what makes it right in the case everybody forgets: a client that joins to find somebody already in a car never ran a transition for them, and would otherwise show a rider standing through the roof. Every machine starts and stops the pose off the replicated phase, so nothing about it is on the wire.
There is nothing to warp to and no notify to fire, so the entry needs little more than the animation:
Phase Tag Mount.Phase.Seated
Animation AS_Sitting
Use Motion Warping false
Tag it with a role to sit a driver differently from a passenger, exactly as you would a transition.
Scripts/build_seated_pose.py in the example project writes a seated pose from six lines describing
where each limb should point. It is worth reading if you have to make one and have no animator.
If the pose plays and nothing moves
Check that your anim graph's slot actually reaches the output pose. A montage plays into a slot by
name, and if the node with that name sits on a branch the graph does not evaluate, everything reports
success and the skeleton never changes: the montage is playing, IsSlotActive is true, and
GetSlotMontageLocalWeight is 1.0. The engine's own ABP_Unarmed is like this, which is why the
example project applies the pose itself instead — see The example.
ResolveSeatedPose on the rider component returns the pose the framework chose, so a project in that
position can apply it whatever way suits its rig.
Seat anim layers
A seat can name a Seat Anim Layer. It is linked onto the rider's anim instance when they attach and unlinked when they leave — the exact class that was linked, so changing the property while somebody is sitting there cannot leave a layer behind.
This is how a rider gets hands-on-wheel behaviour, a lean into corners, or a different idle in the back seat, without the character's anim graph knowing what a vehicle is.
Reading state from an anim graph
Pure nodes that take an actor and need no cast:
Get Mount Phase → None / Entering / Seated / Shuffling / Exiting
Is Seated
Is Driving Mount
Get Seat Role → the seat's role tag
Get Occupied Seat → the seat component, for anything else
A seated pose that differs between the driver and a passenger is one tag comparison, with no dependency from the animation on your game's classes.