Overview
The class_selector_ui_device pops up a Class Selector UI so players can choose their class (Gunner, Lookout, Navigator...) from a menu instead of walking into a physical class-selector volume. You call Show(Agent) to display the menu to a specific player, and you subscribe to its events — ClassSelectedEvent, ClassChangedEvent, UIOpenedEvent, UIClosedEvent — to know exactly when and what a player chose.
Reach for it when you want a clean, on-demand class picker: a player steps onto the dock, the UI opens, they pick their pirate role, and your game reacts — firing a welcome cinematic through a trigger_device and calling out the deck guards with a creature_spawner_device. It's the glue between "player made a choice" and "the island responds."
API Reference
creature_spawner_device
Used to spawn one or more waves of creatures of customizable types at selected time intervals.
Full public surface, resolved verbatim from the live Epic digest (Fortnite.digest.verse).
creature_spawner_device<public> := class<concrete><final>(creative_device_base):
Events (subscribe a handler to react):
| Event | Signature | Description |
|---|---|---|
SpawnedEvent |
SpawnedEvent<public>:listenable(agent) |
Signaled when a creature is spawned. Sends the agent creature who was spawned. |
EliminatedEvent |
EliminatedEvent<public>:listenable(device_ai_interaction_result) |
Signaled when a creature is eliminated. Source is the agent that has eliminated the creature. If the creature was eliminated by a non-agent then Source is 'false'. Target is the creature that was eliminated. |
Methods (call these to make the device act):
| Method | Signature | Description |
|---|---|---|
SpawnAt |
SpawnAt<public>(Position:(/Verse.org/SpatialMath:)vector3, ?Rotation:?(/Verse.org/SpatialMath:)rotation |
Spawn a creature at the given position. When Rotation is not provided, it will default to the Device's rotation. Returns the agent spawned or false if the device has reached its maximum spawn count. This function is <suspends> because it |
Enable |
Enable<public>():void |
Enables this device. |
Disable |
Disable<public>():void |
Disables this device. |
DestroySpawner |
DestroySpawner<public>():void |
Destroys this device. |
EliminateCreatures |
EliminateCreatures<public>():void |
Eliminates all creatures spawned by this device. |
GetSpawnLimit |
GetSpawnLimit<public>()<transacts>:int |
Returns the spawn limit of the device. |
trigger_device
Used to relay events to other linked devices.
Full public surface, resolved verbatim from the live Epic digest (Fortnite.digest.verse). Inherited members are merged from trigger_base_device.
trigger_device<public> := class<concrete><final>(trigger_base_device):
Events (subscribe a handler to react):
| Event | Signature | Description |
|---|---|---|
TriggeredEvent |
TriggeredEvent<public>:listenable(?agent) |
Signaled when an agent triggers this device. Sends the agent that used this device. Returns false if no agent triggered the action (ex: it was triggered through code). |
Methods (call these to make the device act):
| Method | Signature | Description |
|---|---|---|
Trigger |
Trigger<public>(Agent:agent):void |
Triggers this device with Agent being passed as the agent that triggered the action. Use an agent reference when this device is setup to require one (for instance, you want to trigger the device only with a particular agent. |
Trigger |
Trigger<public>():void |
Triggers this device, causing it to activate its TriggeredEvent event. |
Enable |
Enable<public>():void |
Enables this device. |
Disable |
Disable<public>():void |
Disables this device. |
SetMaxTriggerCount |
SetMaxTriggerCount<public>(MaxCount:int):void |
Sets the maximum amount of times this device can trigger. * 0 can be used to indicate no limit on trigger count. * MaxCount is clamped between [0,20]. |
GetMaxTriggerCount |
GetMaxTriggerCount<public>()<transacts>:int |
Gets the maximum amount of times this device can trigger. * 0 indicates no limit on trigger count. |
GetTriggerCountRemaining |
GetTriggerCountRemaining<public>()<transacts>:int |
Returns the number of times that this device can still be triggered before hitting GetMaxTriggerCount. Returns 0 if GetMaxTriggerCount is unlimited. |
SetResetDelay |
SetResetDelay<public>(Time:float):void |
Sets the time (in seconds) after triggering, before the device can be triggered again (if MaxTrigger count allows). |
GetResetDelay |
GetResetDelay<public>()<transacts>:float |
Gets the time (in seconds) before the device can be triggered again (if MaxTrigger count allows). |
SetTransmitDelay |
SetTransmitDelay<public>(Time:float):void |
Sets the time (in seconds) which must pass after triggering, before this device informs other external devices that it has been triggered. |
GetTransmitDelay |
GetTransmitDelay<public>()<transacts>:float |
Gets the time (in seconds) which must pass after triggering, before this device informs other external devices that it has been triggered. |
Walkthrough
Here's the full sunny-dock moment. A player triggers the greeter trigger (by stepping on a linked plate). We show them the Class Selector UI. When they pick a class, we fire a welcome trigger and — if they picked the "Gunner" class (index 0) — spawn a crab creature at the end of the pier to test their aim.
using { /Fortnite.com/Devices }
using { /Fortnite.com }
using { /Verse.org/Simulation }
using { /Verse.org/SpatialMath }
dock_class_picker := class(creative_device):
# The UI menu that shows on the dock.
@editable
ClassMenu : class_selector_ui_device = class_selector_ui_device{}
# A trigger the player steps on to open the menu.
@editable
GreeterTrigger : trigger_device = trigger_device{}
# A trigger that fires the welcome cinematic once a class is chosen.
@editable
WelcomeTrigger : trigger_device = trigger_device{}
# Spawns a crab at the pier's end for Gunners to practice on.
@editable
CrabSpawner : creature_spawner_device = creature_spawner_device{}
OnBegin<override>()<suspends> : void =
# Only let the welcome fire a few times, with a short cooldown.
WelcomeTrigger.SetMaxTriggerCount(5)
WelcomeTrigger.SetResetDelay(2.0)
# When a player steps on the greeter, show them the menu.
GreeterTrigger.TriggeredEvent.Subscribe(OnGreeted)
# React to the player's class choice.
ClassMenu.ClassSelectedEvent.Subscribe(OnClassSelected)
ClassMenu.ClassChangedEvent.Subscribe(OnClassChanged)
# React when a spawned crab is eliminated.
CrabSpawner.EliminatedEvent.Subscribe(OnCrabDown)
# GreeterTrigger hands us ?agent — unwrap before use.
OnGreeted(Agent : ?agent) : void =
if (Player := Agent?):
ClassMenu.Show(Player)
# ClassSelectedEvent hands us a plain agent.
OnClassSelected(Player : agent) : void =
# Fire the welcome cinematic for this player.
WelcomeTrigger.Trigger(Player)
# ClassChangedEvent hands us (agent, int) — the chosen class index.
OnClassChanged(Result : tuple(agent, int)) : void =
Player := Result(0)
ClassIndex := Result(1)
# Class 0 is our "Gunner" — give them a target on the pier.
if (ClassIndex = 0):
spawn { SpawnPracticeCrab() }
SpawnPracticeCrab()<suspends> : void =
PierEnd := vector3{ X := 1200.0, Y := 0.0, Z := 100.0 }
CrabSpawner.SpawnAt(PierEnd, ?Rotation := false)
OnCrabDown(Result : device_ai_interaction_result) : void =
# A guard fell — let the deck know via the welcome trigger.
WelcomeTrigger.Trigger()
Line by line:
- The four
@editablefields are the placed devices; you assign each in the Details panel in UEFN. Without these fields you cannot call the devices from Verse. - In
OnBegin,SetMaxTriggerCount(5)andSetResetDelay(2.0)configure the welcome trigger so it can't spam-fire. GreeterTrigger.TriggeredEvent.Subscribe(OnGreeted)wires the step-on plate to our handler.TriggeredEventislistenable(?agent), soOnGreetedtakes?agentand unwraps it withif (Player := Agent?).ClassMenu.Show(Player)pops the Class Selector UI for that exact player.ClassSelectedEventsends a plainagent, soOnClassSelectedtriggers the welcome cinematic for that player withWelcomeTrigger.Trigger(Player).ClassChangedEventsendstuple(agent, int); we read the index withResult(1)and, if it's the Gunner class (0), spawn a crab at the pier viaSpawnAt.SpawnAtis<suspends>, so we run it in aspawn{}block and pass?Rotation := falseto use the spawner's own rotation.EliminatedEventgives us adevice_ai_interaction_result; when the crab goes down we fireWelcomeTrigger.Trigger()(the no-argument overload).
Common patterns
React to closing the UI — clean up the deck
When a player closes the menu without changing more, disable the practice spawner so no stray crabs wander the dock.
using { /Fortnite.com/Devices }
using { /Fortnite.com }
using { /Verse.org/Simulation }
dock_menu_cleanup := class(creative_device):
@editable
ClassMenu : class_selector_ui_device = class_selector_ui_device{}
@editable
CrabSpawner : creature_spawner_device = creature_spawner_device{}
OnBegin<override>()<suspends> : void =
ClassMenu.UIOpenedEvent.Subscribe(OnOpened)
ClassMenu.UIClosedEvent.Subscribe(OnClosed)
OnOpened(Player : agent) : void =
# Menu is up — the spawner is ready to serve targets.
CrabSpawner.Enable()
OnClosed(Player : agent) : void =
# Player left the menu — clear any crabs and pause the spawner.
CrabSpawner.EliminateCreatures()
CrabSpawner.Disable()
Show the menu manually and count remaining welcomes
Here the trigger's own count decides whether we bother opening the menu — a gate that only greets the first few arrivals.
using { /Fortnite.com/Devices }
using { /Fortnite.com }
using { /Verse.org/Simulation }
dock_gated_greeter := class(creative_device):
@editable
ClassMenu : class_selector_ui_device = class_selector_ui_device{}
@editable
GreeterTrigger : trigger_device = trigger_device{}
OnBegin<override>()<suspends> : void =
GreeterTrigger.SetMaxTriggerCount(3)
GreeterTrigger.TriggeredEvent.Subscribe(OnStep)
OnStep(Agent : ?agent) : void =
if (Player := Agent?):
Remaining := GreeterTrigger.GetTriggerCountRemaining()
if (Remaining > 0):
ClassMenu.Show(Player)
Enable the menu only after the spawner reports a spawn
Keep the picker hidden until the cove's guardian crab has appeared, tying SpawnedEvent to Enable.
using { /Fortnite.com/Devices }
using { /Fortnite.com }
using { /Verse.org/Simulation }
using { /Verse.org/SpatialMath }
dock_reveal_menu := class(creative_device):
@editable
ClassMenu : class_selector_ui_device = class_selector_ui_device{}
@editable
GuardianSpawner : creature_spawner_device = creature_spawner_device{}
OnBegin<override>()<suspends> : void =
ClassMenu.Disable()
GuardianSpawner.SpawnedEvent.Subscribe(OnGuardianUp)
spawn { SpawnGuardian() }
SpawnGuardian()<suspends> : void =
CoveCenter := vector3{ X := 0.0, Y := 800.0, Z := 100.0 }
GuardianSpawner.SpawnAt(CoveCenter, ?Rotation := false)
OnGuardianUp(Creature : agent) : void =
# The guardian is on the dock — now players may pick their class.
ClassMenu.Enable()
Gotchas
- Different events, different payloads.
ClassSelectedEvent,UIOpenedEvent, andUIClosedEventhand you a plainagent.ClassChangedEventhands you atuple(agent, int)— read the player withResult(0)and the class index withResult(1). Don't try to unwrap these withAgent?; only thetrigger_device.TriggeredEventgives?agent. ?agentfrom triggers must be unwrapped.trigger_device.TriggeredEventislistenable(?agent), so your handler takes?agent— always doif (Player := Agent?):before callingShow(Player).Showis notEnable.Show(Agent)displays the menu to one player right now;Enable()/Disable()control whether the device works at all. A disabled device won't show even if you callShow.SpawnAtsuspends.creature_spawner_device.SpawnAtis<suspends>and must run inside a<suspends>context — call it fromOnBegindirectly or wrap it inspawn { ... }. Pass?Rotation := falseto fall back to the spawner's rotation.- Trigger count is clamped.
SetMaxTriggerCountclamps between 0 and 20, and0means unlimited.GetTriggerCountRemaining()returns0when the max is unlimited — so a0remaining doesn't always mean "done." - Two
Triggeroverloads.Trigger(Agent)passes a specific player through the event;Trigger()fires with no agent (itsTriggeredEventthen reportsfalse). Choose based on whether downstream logic needs to know who.