Overview
The changing_booth_device is a Creative device that presents players with an outfit-selection UI when they walk up to it. From a Verse perspective the device exposes two listenable events:
| Event | When it fires | Payload |
|---|---|---|
PlayerEnterEvent |
A player steps into the booth | player |
PlayerExitEvent |
A player leaves the booth (after or without changing) | player |
Reach for this device whenever you need to:
- Gate progression behind a costume change (e.g. "put on the disguise to enter the enemy base").
- Award XP / items the moment a player finishes changing.
- Track stats — count total outfit swaps across all players.
- Trigger cinematics or narrative beats tied to a character transformation.
Because both events carry a player payload you always know who entered or exited, making per-player logic straightforward.
API Reference
changing_booth_device
Allows players to change their outfit in game!
Full public surface, resolved verbatim from the live Epic digest (Fortnite.digest.verse).
changing_booth_device<public> := class<concrete><final>(creative_device_base):
Events (subscribe a handler to react):
| Event | Signature | Description |
|---|---|---|
PlayerEnterEvent |
PlayerEnterEvent<public>:listenable(player) |
Signaled when a player enters the changing booth device. |
PlayerExitEvent |
PlayerExitEvent<public>:listenable(player) |
Signaled when a player exits the changing booth device. |
Walkthrough
Scenario: The Disguise Gate
You have a spy-themed map. A locked barrier blocks the path to the enemy base. Players must step into a changing_booth_device (to put on a disguise) before the barrier opens. Once they exit the booth the barrier unlocks for that player and a confirmation message is broadcast.
Place these devices on your island:
- One
changing_booth_device(the disguise booth) - One
barrier_device(the gate — set it to Enabled / blocking by default in its properties) - One
hud_message_device(optional — to show the "Disguise acquired" message)
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/Diagnostics }
# disguise_gate_device.verse
# Drop this Verse device on the island, then wire up the three @editable fields.
disguise_gate_device := class(creative_device):
# The changing booth the player must use to get their disguise.
@editable
DisguiseBooth : changing_booth_device = changing_booth_device{}
# The barrier that blocks the path to the enemy base.
@editable
Gate : barrier_device = barrier_device{}
# A HUD message device to confirm the disguise was acquired.
@editable
ConfirmationHUD : hud_message_device = hud_message_device{}
# Tracks how many players have successfully changed.
var DisguisedCount : int = 0
OnBegin<override>()<suspends> : void =
# Subscribe both events so we react to enter AND exit.
DisguiseBooth.PlayerEnterEvent.Subscribe(OnPlayerEnterBooth)
DisguiseBooth.PlayerExitEvent.Subscribe(OnPlayerExitBooth)
# Called the moment a player steps INTO the booth.
# Use this to give a hint or start a timer if you like.
OnPlayerEnterBooth(P : player) : void =
# The player is now inside — we could start a countdown here.
# For this example we just wait for them to exit.
Print("A player entered the disguise booth.")
# Called when a player EXITS the booth (whether they changed or not).
# We treat any exit as "disguise acquired" for simplicity.
OnPlayerExitBooth(P : player) : void =
# Increment the global counter.
set DisguisedCount = DisguisedCount + 1
# Unlock the gate for everyone once at least one player has changed.
# (Swap this logic for per-player gating if your game needs it.)
Gate.Disable()
# Show the confirmation message.
ConfirmationHUD.Show()
Print("Disguise acquired! Total disguised players: {DisguisedCount}")
Line-by-line explanation
| Lines | What's happening |
|---|---|
@editable fields |
Wired in the UEFN editor — no hard-coded device names. |
var DisguisedCount |
A mutable counter that persists for the session. |
OnBegin |
Runs at game start; subscribes both events so handlers fire automatically. |
OnPlayerEnterBooth |
Fires the instant a player walks into the booth UI. Great for hints or timers. |
OnPlayerExitBooth |
Fires when the player leaves — this is where we unlock the gate and show the HUD. |
Gate.Disable() |
Disables the barrier device, opening the path. |
ConfirmationHUD.Show() |
Pops the HUD message so the player knows they're good to go. |
Common patterns
Pattern 1 — Count how many players are currently inside the booth
Sometimes you want to know whether anyone is actively in the booth right now (e.g. to prevent the booth being used while a cinematic plays).
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/Diagnostics }
booth_occupancy_tracker := class(creative_device):
@editable
Booth : changing_booth_device = changing_booth_device{}
# How many players are currently inside the booth.
var PlayersInside : int = 0
OnBegin<override>()<suspends> : void =
Booth.PlayerEnterEvent.Subscribe(OnEnter)
Booth.PlayerExitEvent.Subscribe(OnExit)
OnEnter(P : player) : void =
set PlayersInside = PlayersInside + 1
Print("Booth occupancy: {PlayersInside}")
OnExit(P : player) : void =
if (PlayersInside > 0):
set PlayersInside = PlayersInside - 1
Print("Booth occupancy: {PlayersInside}")
This pattern is useful as a guard: check PlayersInside > 0 before triggering anything that would conflict with the booth UI.
Pattern 2 — Award an item the moment a player exits the booth
Pair the booth with an item_granter_device to hand a weapon or consumable to every player who completes a costume change.
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/Diagnostics }
booth_item_reward_device := class(creative_device):
@editable
DisguiseBooth : changing_booth_device = changing_booth_device{}
# An item_granter_device pre-configured in the editor with the reward item.
@editable
Granter : item_granter_device = item_granter_device{}
OnBegin<override>()<suspends> : void =
# Only subscribe to PlayerExitEvent — we reward on exit, not entry.
DisguiseBooth.PlayerExitEvent.Subscribe(OnExitBooth)
OnExitBooth(P : player) : void =
# Grant the configured item to the player who just exited.
Granter.GrantItem(P)
Print("Item granted to player who exited the booth.")
item_granter_device.GrantItem(agent) targets a specific player, so every person who exits gets their own reward independently.
Pattern 3 — Fire a cinematic the first time any player enters the booth
Trigger a one-shot narrative moment (via a cinematic_sequence_device) the very first time a player steps into the booth.
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/Diagnostics }
booth_cinematic_device := class(creative_device):
@editable
DisguiseBooth : changing_booth_device = changing_booth_device{}
@editable
Cinematic : cinematic_sequence_device = cinematic_sequence_device{}
# Guard so the cinematic only plays once.
var CinematicPlayed : logic = false
OnBegin<override>()<suspends> : void =
DisguiseBooth.PlayerEnterEvent.Subscribe(OnFirstEnter)
OnFirstEnter(P : player) : void =
if (CinematicPlayed = false):
set CinematicPlayed = true
Cinematic.Play()
Print("Cinematic triggered by first booth entry.")
The logic guard ensures Cinematic.Play() is called exactly once no matter how many players use the booth.
Gotchas
1. Both events carry player, not ?agent
PlayerEnterEvent and PlayerExitEvent are listenable(player) — the payload is a concrete player, not ?agent. You do not need to unwrap an option; just use P : player directly in your handler signature. Contrast this with some other devices whose events send ?agent and require if (A := Agent?): unwrapping.
2. Exit fires whether or not the player changed outfit
PlayerExitEvent fires whenever the player leaves the booth UI — even if they closed it without picking a new outfit. If your game logic requires confirming an actual outfit change you will need additional state (e.g. compare the player's cosmetic before and after, or require them to interact with a separate confirmation button).
3. Subscribe in OnBegin, not at field-initialisation time
You must call .Subscribe(...) inside OnBegin<override>()<suspends>. Attempting to subscribe at class-field level (outside a method) will not compile because the device references are not yet valid.
4. No methods — only events
changing_booth_device exposes zero callable methods. You cannot programmatically open the booth UI, force a player into it, or query which outfit a player chose. All Verse interaction is purely reactive via the two events.
5. One handler per subscription call
Each call to .Subscribe(Handler) registers one callback. If you accidentally call Subscribe twice in a loop or from two code paths, your handler will fire twice per event. Keep subscription calls in a single, clearly guarded location (typically OnBegin).
6. message parameters need localisation helpers
If you pass text to a device that accepts a message type (e.g. hud_message_device), raw strings are not accepted. Declare a localised helper:
MyText<localizes>(S : string) : message = "{S}"
and pass MyText("Disguise acquired!") — there is no StringToMessage function in Verse.