Overview
The chair_device creates a seat that any qualifying agent can sit on. It looks like furniture, but from a Verse perspective it's a precise, per-agent interaction surface. The moment a player sits, SeatedEvent fires and hands you the sitting agent — perfect for kicking off cinematics, granting items, starting a getaway-vehicle sequence, or scoring a "capture the throne" objective.
Reach for the chair_device when you want a player to commit to a spot: a barber chair before a makeover, a cockpit before a launch, an interrogation chair you can lock them into, or a king's throne that only one team may hold. You can Seat and Eject agents programmatically, toggle whether they're even allowed to leave with EnableExit/DisableExit, and query the seat state with IsSeated, IsOccupied, and GetSeatedAgent.
Because SeatedEvent and ExitedEvent are listenable(agent), the handler receives an ?agent you must unwrap before using it. The rest of this article walks through a full example, then covers each method in focused snippets.
API Reference
chair_device
Creates a chair where
Agents can sit.
Full public surface, resolved verbatim from the live Epic digest (Fortnite.digest.verse).
chair_device<public> := class<concrete><final>(creative_device_base):
Events (subscribe a handler to react):
| Event | Signature | Description |
|---|---|---|
SeatedEvent |
SeatedEvent<public>:listenable(agent) |
Signaled when an agent sits on the Chair. Sends the sitting agent. |
ExitedEvent |
ExitedEvent<public>:listenable(agent) |
Signaled when an agent stops sitting on the Chair. Sends the standing Agent. |
Methods (call these to make the device act):
| Method | Signature | Description |
|---|---|---|
Enable |
Enable<public>():void |
Enables the Chair. An enabled Chair can be interacted with and occupied by any agent that meets the requirements. |
Disable |
Disable<public>():void |
Disables the Chair. A disabled Chair cannot be interacted with and any agent currently occupying the Chair will be ejected. |
EnableExit |
EnableExit<public>():void |
Allows any seated agent to leave the chair manually. |
DisableExit |
DisableExit<public>():void |
Prevents any seated agent from leaving the Chair manually. While Exit is disabled, call Eject to force them out. |
Seat |
Seat<public>(Agent:agent):void |
Makes Agent sit on this chair if they meet the requirements. |
Eject |
Eject<public>():void |
Ejects any agent currently in the chair. |
Eject |
Eject<public>(Agent:agent):void |
Makes Agent exit this chair if they are currently in the chair. |
IsSeated |
IsSeated<public>(Agent:agent)<transacts><decides>:void |
Succeeds if Agent is currently in the chair . |
IsOccupied |
IsOccupied<public>()<transacts><decides>:void |
Succeeds if the chair is currently occupied. |
GetSeatedAgent |
GetSeatedAgent<public>():?agent |
Returns the agent currently occupying the chair. |
Walkthrough
Let's build a "Throne of Power" scenario. A throne (the chair) sits in the middle of the map. When a player sits on it, we lock them in so they can't immediately leave, light up a victory prop, and after they've claimed it the throne stays occupied until we eject them. We'll use SeatedEvent, ExitedEvent, DisableExit, EnableExit, Eject, GetSeatedAgent, and Show/Hide on a prop.
using { /Fortnite.com/Devices }
using { /Fortnite.com }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/SpatialMath }
# A throne that locks the first player who sits, lights a victory prop,
# and releases them after a short reign.
throne_of_power := class(creative_device):
# The chair placed in the level — drag your chair_device here in the Details panel.
@editable
Throne : chair_device = chair_device{}
# A prop (e.g. a glowing crown) we Show while the throne is claimed.
@editable
VictoryProp : creative_prop = creative_prop{}
# How long (seconds) a reign lasts before we eject the ruler.
@editable
ReignSeconds : float = 8.0
OnBegin<override>()<suspends> : void =
# Hide the victory prop until someone claims the throne.
VictoryProp.Hide()
# React when an agent sits or leaves.
Throne.SeatedEvent.Subscribe(OnSeated)
Throne.ExitedEvent.Subscribe(OnExited)
# Runs when ANY agent sits on the throne.
OnSeated(Agent : agent) : void =
# Lock them in: they cannot stand up manually now.
Throne.DisableExit()
# Light up the crown.
VictoryProp.Show()
# Start the reign timer concurrently so OnSeated returns immediately.
spawn { ReignCountdown(Agent) }
# Runs when an agent leaves (or is ejected from) the throne.
OnExited(Agent : agent) : void =
# Hide the crown again once the seat is empty.
VictoryProp.Hide()
# Re-allow manual exit so the next ruler isn't pre-locked.
Throne.EnableExit()
# Suspends for the reign duration, then forces the ruler out.
ReignCountdown(Agent : agent)<suspends> : void =
Sleep(ReignSeconds)
# Only eject if this exact agent is still seated.
if (Throne.IsSeated[Agent]):
Throne.Eject(Agent)
Line by line:
- The
@editableThrone : chair_devicefield is what lets Verse talk to the chair you placed in the level. Without an editable field, callingThrone.Anything()would fail with "Unknown identifier." VictoryProp.Hide()inOnBeginmakes sure the crown starts invisible (with collisions off).Throne.SeatedEvent.Subscribe(OnSeated)andThrone.ExitedEvent.Subscribe(OnExited)register our class methods as handlers. Both events arelistenable(agent), so each handler signature is(Agent : agent).- In
OnSeated,Throne.DisableExit()prevents the seated player from standing on their own — they're locked to the throne until we eject them. spawn { ReignCountdown(Agent) }launches the timer as a concurrent task so the event handler returns promptly.ReignCountdownis marked<suspends>because it callsSleep.- In
ReignCountdown,Sleep(ReignSeconds)waits out the reign. We then guard withif (Throne.IsSeated[Agent])—IsSeatedis a<decides>function, so it goes in[]brackets — and onlyEjectthe agent if they're still the one sitting. (They might have been ejected by other logic already.) OnExitedhides the crown and callsEnableExit()so the next person who sits isn't already locked.
Common patterns
Force a player into a seat with Seat
Great for a getaway-car cutscene: when the round ends you slam the winner into a vehicle chair. Here we seat the agent who triggers a button.
using { /Fortnite.com/Devices }
using { /Fortnite.com }
using { /Verse.org/Simulation }
force_seater := class(creative_device):
@editable
GetawayChair : chair_device = chair_device{}
@editable
BoardButton : button_device = button_device{}
OnBegin<override>()<suspends> : void =
BoardButton.InteractedWithEvent.Subscribe(OnPressed)
OnPressed(Agent : agent) : void =
# Put the pressing agent straight into the chair.
GetawayChair.Seat(Agent)
Query occupancy with IsOccupied and GetSeatedAgent
For a "only one ruler at a time" gate: when someone steps on a plate, check if the throne is already taken before letting them try.
using { /Fortnite.com/Devices }
using { /Fortnite.com }
using { /Verse.org/Simulation }
throne_checker := class(creative_device):
@editable
Throne : chair_device = chair_device{}
@editable
ClaimPlate : trigger_device = trigger_device{}
OnBegin<override>()<suspends> : void =
ClaimPlate.TriggeredEvent.Subscribe(OnPlate)
OnPlate(MaybeAgent : ?agent) : void =
if (Agent := MaybeAgent?):
if (Throne.IsOccupied[]):
# Already taken — who holds it?
if (Ruler := Throne.GetSeatedAgent[]):
# Ruler currently rules; do nothing (or eject them, your call).
Throne.Eject(Ruler)
else:
# Empty — seat the challenger.
Throne.Seat(Agent)
Enable and disable the whole chair
Use Enable/Disable to gate the chair by game phase. A disabled chair ejects anyone in it and can't be interacted with — handy for closing a cockpit between rounds.
using { /Fortnite.com/Devices }
using { /Fortnite.com }
using { /Verse.org/Simulation }
chair_phase_gate := class(creative_device):
@editable
Cockpit : chair_device = chair_device{}
@editable
OpenButton : button_device = button_device{}
@editable
CloseButton : button_device = button_device{}
OnBegin<override>()<suspends> : void =
# Start closed.
Cockpit.Disable()
OpenButton.InteractedWithEvent.Subscribe(OnOpen)
CloseButton.InteractedWithEvent.Subscribe(OnClose)
OnOpen(Agent : agent) : void =
Cockpit.Enable()
OnClose(Agent : agent) : void =
# Disabling ejects anyone currently seated.
Cockpit.Disable()
Gotchas
SeatedEvent/ExitedEventarelistenable(agent), notlistenable(?agent). Their handlers receive a plainagent— you do NOT need to unwrap them. But events from OTHER devices (liketrigger_device.TriggeredEvent) hand you?agent, which you DO unwrap withif (A := MaybeAgent?):. Don't mix them up.IsSeated,IsOccupied, andGetSeatedAgentare failable.IsSeated[Agent]andIsOccupied[]are<decides>and must be called inside[]within anif.GetSeatedAgentreturns a?agent, so unwrap it:if (Ruler := Throne.GetSeatedAgent[]):— actually it's a function returning an option, so useif (Ruler := Throne.GetSeatedAgent()?):if you call it as a method. In the snippet above the bracket form unwraps the option directly.DisableExitdoes not eject anyone. It only blocks manual exit. To remove a locked player you must callEject. If you forget to callEnableExitafterward, the next seated player will also be locked.Disableis destructive. Disabling the chair instantly ejects the current occupant. Don't disable mid-cinematic unless you intend to interrupt it.Seat(Agent)can silently do nothing if the agent doesn't meet the chair's configured requirements (team, class, etc.) or is already seated elsewhere. Verify withIsSeated[Agent]afterward if the seating is gameplay-critical.- Two
Ejectoverloads exist.Eject()(no args) removes whoever is currently in the chair;Eject(Agent)removes a specific agent only if they're the one seated. Pick the one that matches your intent.