Overview
The gameplay_controls_third_person_device is a Gameplay Controls device that changes how a player's input maps to their character movement and camera. Rather than replacing the player's entire control scheme permanently, it pushes itself onto a per-agent controls stack with AddTo / AddToAll, and pops itself back off with RemoveFrom / RemoveFromAll. This means you can layer control changes safely — the moment you remove the device, the player's previous controls return automatically.
When to reach for it:
- A boss arena that forces third-person so players can see the full battlefield.
- A cinematic-style intro where everyone drops into third-person while a sequence plays.
- A single player who enters a special zone (a vault, a puzzle room) and needs a different perspective.
- Any time you want to temporarily override controls without permanently breaking the default scheme.
The device must be placed in the UEFN level and referenced via an @editable field — you cannot construct it in Verse code alone.
API Reference
gameplay_controls_third_person_device
Used to adapt the controls to the camera perspective
Full public surface, resolved verbatim from the live Epic digest (Fortnite.digest.verse). Inherited members are merged from gameplay_controls_device.
gameplay_controls_third_person_device<public> := class<concrete><final>(gameplay_controls_device):
Methods (call these to make the device act):
| Method | Signature | Description |
|---|---|---|
Enable |
Enable<public>():void |
Enables this device. |
Disable |
Disable<public>():void |
Disables this device. |
AddTo |
AddTo<public>(Agent:agent):void |
Adds the gameplay control to the Player's gameplay controls stack and pushes it to be the active control. |
AddToAll |
AddToAll<public>():void |
Adds the gameplay control to all Agents gameplay controls stack and pushes it to be the active control. |
RemoveFrom |
RemoveFrom<public>(Agent:agent):void |
Removes the gameplay control from the Agent's gameplay controls stack and pops from being the active control replacing it with the next one in the stack. |
RemoveFromAll |
RemoveFromAll<public>():void |
Removes the gameplay control from all Agents gameplay controls stack and pops from being the active control replacing it with the next one in the stack. |
gameplay_controls_device
Used to update the gameplay controls scheme based on current control mode.
Full public surface, resolved verbatim from the live Epic digest (Fortnite.digest.verse).
gameplay_controls_device<public> := class<abstract><epic_internal>(creative_device_base):
Methods (call these to make the device act):
| Method | Signature | Description |
|---|---|---|
Enable |
Enable<public>():void |
Enables this device. |
Disable |
Disable<public>():void |
Disables this device. |
AddTo |
AddTo<public>(Agent:agent):void |
Adds the gameplay control to the Player's gameplay controls stack and pushes it to be the active control. |
AddToAll |
AddToAll<public>():void |
Adds the gameplay control to all Agents gameplay controls stack and pushes it to be the active control. |
RemoveFrom |
RemoveFrom<public>(Agent:agent):void |
Removes the gameplay control from the Agent's gameplay controls stack and pops from being the active control replacing it with the next one in the stack. |
RemoveFromAll |
RemoveFromAll<public>():void |
Removes the gameplay control from all Agents gameplay controls stack and pops from being the active control replacing it with the next one in the stack. |
Walkthrough
Scenario: A haunted vault. When a player steps on a pressure plate outside the vault door, the vault door opens, the player is switched to third-person so they can see the monster inside, and when they leave a second trigger they're switched back to normal controls.
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /Fortnite.com/Playspaces }
using { /Fortnite.com/Characters }
# vault_controller.verse
# Switches a player to third-person when they enter the vault,
# and restores controls when they exit.
vault_controller := class(creative_device):
# The third-person controls device placed in the level
@editable
ThirdPersonControls : gameplay_controls_third_person_device = gameplay_controls_third_person_device{}
# Trigger placed at the vault entrance — player steps on it to enter
@editable
EnterTrigger : trigger_device = trigger_device{}
# Trigger placed at the vault exit — player steps on it to leave
@editable
ExitTrigger : trigger_device = trigger_device{}
# Called when the experience starts
OnBegin<override>()<suspends> : void =
# Enable the controls device so it can be pushed onto stacks
ThirdPersonControls.Enable()
# Subscribe to the entrance trigger
EnterTrigger.TriggeredEvent.Subscribe(OnPlayerEnterVault)
# Subscribe to the exit trigger
ExitTrigger.TriggeredEvent.Subscribe(OnPlayerExitVault)
# Handler: player steps into the vault
OnPlayerEnterVault(Agent : ?agent) : void =
# Unwrap the optional agent — the trigger sends ?agent
if (A := Agent?):
# Push third-person onto this player's controls stack
ThirdPersonControls.AddTo(A)
# Handler: player steps out of the vault
OnPlayerExitVault(Agent : ?agent) : void =
if (A := Agent?):
# Pop third-person off this player's controls stack,
# restoring whatever was active before
ThirdPersonControls.RemoveFrom(A)
Line-by-line breakdown:
| Line | What it does |
|---|---|
ThirdPersonControls.Enable() |
Arms the device so it can be pushed onto control stacks. Without this call the AddTo / AddToAll calls are silently ignored. |
EnterTrigger.TriggeredEvent.Subscribe(OnPlayerEnterVault) |
Registers the handler at class scope — the trigger fires it whenever any agent steps on the plate. |
if (A := Agent?) |
TriggeredEvent delivers a ?agent (optional). We must unwrap it before passing it to AddTo. |
ThirdPersonControls.AddTo(A) |
Pushes third-person onto this specific player's controls stack. Other players are unaffected. |
ThirdPersonControls.RemoveFrom(A) |
Pops third-person off the stack. The engine automatically activates whatever control scheme was underneath. |
Common patterns
Pattern 1 — Flip everyone to third-person at round start, restore at round end
Useful for a battle-royale-style opening where all players drop in with a cinematic third-person view.
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
# round_start_controller.verse
# Adds third-person controls to ALL players when the round timer ends,
# then removes them after a fixed delay.
round_start_controller := class(creative_device):
@editable
ThirdPersonControls : gameplay_controls_third_person_device = gameplay_controls_third_person_device{}
# A timer device set to fire once at round start
@editable
RoundTimer : timer_device = timer_device{}
OnBegin<override>()<suspends> : void =
ThirdPersonControls.Enable()
RoundTimer.SuccessEvent.Subscribe(OnRoundStart)
OnRoundStart(Agent : ?agent) : void =
# Push third-person onto every connected player's stack at once
ThirdPersonControls.AddToAll()
# After 10 seconds, pop it off for everyone
Sleep(10.0)
ThirdPersonControls.RemoveFromAll()
Pattern 2 — Disable the device to prevent it from being pushed mid-game
Sometimes you want to lock out the third-person controls device during a phase where it shouldn't be usable (e.g., during a cutscene that handles its own camera). Disable prevents any future AddTo calls from taking effect until you Enable it again.
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
# cutscene_lock_controller.verse
# Disables the third-person controls device while a cinematic plays,
# then re-enables it when the cinematic ends.
cutscene_lock_controller := class(creative_device):
@editable
ThirdPersonControls : gameplay_controls_third_person_device = gameplay_controls_third_person_device{}
@editable
CinematicSequence : cinematic_sequence_device = cinematic_sequence_device{}
OnBegin<override>()<suspends> : void =
ThirdPersonControls.Enable()
CinematicSequence.PlayedEvent.Subscribe(OnCinematicStarted)
CinematicSequence.StoppedEvent.Subscribe(OnCinematicEnded)
OnCinematicStarted(Agent : ?agent) : void =
# Lock out third-person controls while the cinematic owns the camera
ThirdPersonControls.Disable()
OnCinematicEnded(Agent : ?agent) : void =
# Re-arm the device so players can enter third-person zones again
ThirdPersonControls.Enable()
Pattern 3 — Per-player third-person in a special zone, using GetPlayers to seed existing players
If your experience starts with players already in the world, you need to handle them at OnBegin as well as new arrivals.
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /Fortnite.com/Playspaces }
# zone_third_person_controller.verse
# Gives all current players third-person controls immediately,
# and also handles any player who joins after start.
zone_third_person_controller := class(creative_device):
@editable
ThirdPersonControls : gameplay_controls_third_person_device = gameplay_controls_third_person_device{}
OnBegin<override>()<suspends> : void =
ThirdPersonControls.Enable()
# Apply to all players already in the session
ThirdPersonControls.AddToAll()
# Also apply to any player who joins later
Playspace := GetPlayspace()
Playspace.PlayerAddedEvent().Subscribe(OnPlayerJoined)
OnPlayerJoined(NewPlayer : player) : void =
# Push third-person onto the new arrival's stack
ThirdPersonControls.AddTo(NewPlayer)
Gotchas
1. You MUST call Enable() before AddTo / AddToAll
The device ships disabled by default (or may be configured that way in the editor). Calling AddTo on a disabled device silently does nothing — no error, no effect. Always call ThirdPersonControls.Enable() in OnBegin unless you have a deliberate reason to leave it disabled.
2. TriggeredEvent delivers ?agent, not agent
The trigger's event payload is an optional agent. If you write ThirdPersonControls.AddTo(Agent) directly you'll get a type error because AddTo expects agent, not ?agent. Always unwrap first:
if (A := Agent?):
ThirdPersonControls.AddTo(A)
3. AddToAll vs AddTo — scope matters
AddToAll pushes the device onto every current agent's stack at the moment of the call. Players who join after that call are not automatically enrolled — you must subscribe to PlayerAddedEvent and call AddTo for latecomers (see Pattern 3).
4. Stack semantics — don't double-push
Calling AddTo on the same agent twice pushes the device onto their stack twice. You'll then need to call RemoveFrom twice to fully pop it. Track whether a player already has the control active, or use RemoveFrom defensively before AddTo if you're unsure.
5. RemoveFromAll only removes from current agents
Just like AddToAll, RemoveFromAll only affects agents present at call time. If a player joined after AddToAll and you only call RemoveFromAll, that late-joiner retains the third-person controls. Mirror your add/remove strategy: if you used per-player AddTo, use per-player RemoveFrom.
6. The device must be placed in the level — you cannot new it
gameplay_controls_third_person_device is <concrete><final> and is a UEFN placed device. Declaring it as @editable and wiring it in the editor is the only valid way to get a reference. A bare gameplay_controls_third_person_device{} in an @editable field is the correct default initializer syntax, but the actual instance must come from the editor.