Seats and entry points
A seat is a UEDMountPointComponent: a scene component, so it has a transform you drag and a parent it
follows.
Placing a seat
Add the component and drag it. The box is the seat; the arrow is the direction the rider faces.
Parent it to a bone when the seat moves. A seat attached to a skeletal mesh socket follows that socket every frame, with no code and no tick — the transform comes from the attachment. That is how
- a saddle stays on a horse that is breathing and galloping,
- a turret gunner turns with the gun,
- a seat inside a door swings out with the door.
Attach Socket Override covers the case where you cannot parent the component but still need to follow
a socket. Parenting is better whenever it is available, because then the transform you see in the
viewport is exactly the transform the rider gets.
Properties
| Property | Default | What it is for |
|---|---|---|
| Seat Name | the component's name | Logs, the editor, and one lookup at setup. Not for gameplay. |
| Role Tag | Mount.Role.Passenger | Mount.Role.Driver is the only one the framework acts on. |
| Sort Priority | 0 | Higher seats are offered first when a rider asks for "any seat". |
| Enabled | true | Takes a seat out of service without deleting it. |
| Required Rider Tags | empty | A query against the rider's tags. See Access rules. |
| Allow Shuffle Into | true | Off makes a seat reachable only from outside. |
| Prefer Same Side On Exit | true | Put the rider down on the side they came in on. |
| Animation Set Override | none | For the seat that genuinely animates differently. |
| Seat Anim Layer | none | An anim layer linked onto the rider while they occupy this seat. |
| Seat Camera | none | A component your camera system can ask about. |
| Rider Policy | project default | Collision, movement, mesh and pose handling while seated. |
| Possession Policy | project default | Whether the controller possesses the mount. |
Addressing a seat
FEDSeatHandle, and nothing else. A stable id issued when the seat registers, valid on every machine,
unchanged when seats are added or removed at runtime.
// Once, at setup:
const FEDSeatHandle GunnerSeat = Mountable->FindSeatByName(TEXT("Gunner"));
// Then, forever:
Rider->RequestChangeSeat(GunnerSeat);
Mounting systems commonly address seats by index and by id and by name, and therefore ship
three variants of every seat function. Worse than the size: index and id drift apart the first time a
seat is removed, and nothing in the type system stops you passing one where the other belongs, because
both are int32.
Entry points
Each seat carries any number of entry points: the places a rider stands to get in, and can be put down when they get out. A car door is one. A roof hatch is one.
An entry point is a transform relative to the seat — so it moves when you move the seat — a side tag, and a capsule describing how much room a rider needs there.
| Property | Default | What it is for |
|---|---|---|
| Side Tag | derived from geometry | Mount.Entry.Left, .Right, .Front, .Rear, .Top. Picks an animation. |
| Relative Transform | identity | Where the rider stands, and which way they face. |
| Priority | 0 | Higher wins among usable points. Ties break on distance. |
| Allow Entry / Allow Exit | true | A hatch you can climb in through but not out of. |
| Clearance Radius / Half Height | 34 / 88 | The capsule swept against the world. Matches the engine's character. |
| Require Ground On Exit | true | Off for a hatch over open air. |
| Max Ground Drop | 200 | How far below the point ground still counts as a floor. |
Leaving them empty
A seat with no entry points is a valid state: the framework derives a left/right pair from the mount's bounds. They are drawn dashed, because they are a preview rather than data.
Press Generate Entry Points to write them into the array, then drag them.
How one gets chosen
- Skip it if it does not allow the direction being asked for.
- Sweep its clearance capsule against the world, ignoring the mount and the rider. Skip it if something is in the way.
- For an exit, trace down for ground when the point asks for it.
- Score it:
Priority × 1000 − distance to the rider, plus 500 when it matches the side the caller asked for or the side the rider came in on.
Highest score wins. Priority dominates by design — the spread is wide enough that no realistic distance crosses it, so "priority 1 beats priority 0" is a promise rather than a tendency.
If nothing is usable, entering fails with NoEntryPoint.
When every exit is blocked
Project setting Allow Unsafe Exit Fallback, on by default. On, the rider is placed at the seat and
left to the movement component's own depenetration, which reads as squeezing out of a wedged car. Off,
the dismount is refused with NoExitPoint, which is right for games where being trapped is a state
rather than a bug.
ForceDismount() ignores this entirely. It exists for the vehicle exploding.
The visualizer
| Colour | Meaning |
|---|---|
| Blue box | A free seat. Grey when disabled. |
| Green capsule | A rider fits here, both in and out. |
| Amber capsule | A rider fits, but there is no ground for an exit. |
| Red capsule | Blocked. |
| Yellow | Selected — drag it with the move gizmo. |
| Dashed line | A derived entry point, not real data yet. |
The capsule drawn is the capsule actually swept, so "it says clear but the rider clips the door frame" is impossible to misread. The check runs live: push a wall against a door and watch it change.
Dragging an entry point re-derives its side tag from where it ends up. Fix Side Tags does the same to every point at once, which is the repair for a layout copied from another vehicle.
Adding seats at runtime
UEDMountPointComponent* Seat = NewObject<UEDMountPointComponent>(MountActor);
Seat->SetupAttachment(MountActor->GetRootComponent());
Seat->SeatName = TEXT("JumpSeat");
Seat->RegisterComponent(); // registers itself, and gets a handle
Removing a seat under an occupant force-dismounts them rather than leaving them attached to a component that no longer exists.