Overview
An array in Verse is an ordered, fixed-size collection of values written with [] syntax — []trigger_device, []int, []string, etc. Iteration means visiting each element in turn so you can call a method on it, read it, or make a decision. In UEFN this pattern is everywhere:
- Fire every cannon on a pirate ship when the alarm sounds.
- Show a different HUD message to each player at round start.
- Enable or disable a row of pressure plates based on game state.
You reach for array iteration whenever you have N things of the same type and want to act on all of them without copy-pasting code. The primary tool is the for expression; the primary pitfall is forgetting that array indexing is a failable context.
API Reference
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. |
hud_message_device
Used to show custom HUD messages to one or more
agents.
Full public surface, resolved verbatim from the live Epic digest (Fortnite.digest.verse).
hud_message_device<public> := class<concrete><final>(creative_device_base):
Events (subscribe a handler to react):
| Event | Signature | Description |
|---|---|---|
ShowMessageEvent |
ShowMessageEvent<public>:listenable(agent) |
Called when a Message has been Shown on-screen. Returns an Agent if it was Shown on a specified Agent's screen. |
HideMessageEvent |
HideMessageEvent<public>:listenable(agent) |
Called when a Message has been Hidden on-screen. Returns an Agent if it was Hidden from a specified Agent's screen. |
ClearAllMessagesEvent |
ClearAllMessagesEvent<public>:listenable(agent) |
Called when all queued Messages from all players that are affected by this HUD Message Device have been cleared. |
Methods (call these to make the device act):
| Method | Signature | Description |
|---|---|---|
Show |
Show<public>(Agent:agent):void |
Shows the currently set HUD Message on Agents screen. Will replace any previously active message. Use this when the device is setup to target specific agents. |
Show |
Show<public>():void |
Shows the currently set Message HUD message on screen. Will replace any previously active message. |
Hide |
Hide<public>():void |
Hides the HUD message. |
Hide |
Hide<public>(Agent:agent):void |
Hides the currently set HUD Message on Agents screen. Use this when the device is setup to target specific agents. |
Show |
Show<public>(Agent:agent, Message:message, ?DisplayTime:float |
Displays a Custom message to a specific Agent that you define.Setting DisplayTime to 0.0 will display the HUD message persistently.If not defined, or less than 0.0 the message will show for the time set on the device. |
Show |
Show<public>(Message:message, ?DisplayTime:float |
Displays a Custom message that you define for all PlayersSetting DisplayTime to 0.0 will display the HUD message persistently.If not defined, or less than 0.0 the message will show for the time set on the device. |
SetDisplayTime |
SetDisplayTime<public>(Time:float):void |
Sets the time (in seconds) the HUD message will be displayed. 0.0 will display the HUD message persistently. |
GetDisplayTime |
GetDisplayTime<public>()<transacts>:float |
Returns the time (in seconds) for which the HUD message will be displayed. 0.0 means the message is displayed persistently. |
SetText |
SetText<public>(Text:message):void |
Sets the Message to be displayed when the HUD message is activated. Text is clamped to 150 characters. |
ClearAllMessages |
ClearAllMessages<public>():void |
Clears all queued Messages from all players that are affected by this HUD Message Device. |
player
Full public surface, resolved verbatim from the live Epic digest (Verse.digest.verse). Inherited members are merged from agent.
player<native><public> := class<unique><persistent><module_scoped_var_weak_map_key><epic_internal>(agent):
Walkthrough
Scenario — The Pirate Cove Alarm
Your cel-shaded lagoon island has a wooden dock stretching into a sunny cove. Five trigger_devices represent signal cannons bolted to the dock posts. One extra trigger sits on the crow's-nest platform — when a player steps on it the alarm fires:
- Every cannon trigger fires in sequence (with a short delay between each).
- Each cannon's HUD message device flashes a warning to ALL players.
- The crow's-nest trigger disables itself so it can only fire once.
Place in UEFN:
- 1 ×
trigger_devicenamed CrowsNestTrigger (crow's-nest pressure plate) - 5 ×
trigger_devicenamed CannonTrigger0–4 (the dock cannons) - 5 ×
hud_message_devicenamed CannonHUD0–4 (one per cannon, pre-configured with a warning text)
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
# Localised helper — message params must be `message`, not raw string
CannonWarning<localizes>(S : string) : message = "{S}"
pirate_cove_alarm := class(creative_device):
# The crow's-nest pressure plate that starts the alarm
@editable
CrowsNestTrigger : trigger_device = trigger_device{}
# Five dock cannons — iterate this array to fire them all
@editable
CannonTriggers : []trigger_device = array{}
# One HUD message device per cannon — parallel array, same indices
@editable
CannonHUDs : []hud_message_device = array{}
# Seconds between each cannon firing
@editable
FireDelay : float = 0.4
OnBegin<override>()<suspends> : void =
# Allow the crow's-nest trigger to fire exactly once
CrowsNestTrigger.SetMaxTriggerCount(1)
# Subscribe: when a player steps on the crow's nest, run OnAlarmRaised
CrowsNestTrigger.TriggeredEvent.Subscribe(OnAlarmRaised)
# Called when the crow's-nest trigger fires.
# TriggeredEvent sends ?agent, so the param is ?agent.
OnAlarmRaised(MaybeAgent : ?agent) : void =
# Disable the crow's nest so no second alarm can start
CrowsNestTrigger.Disable()
# Spawn a concurrent task so we can Sleep between cannon shots
spawn { FireAllCannons() }
# Fires each cannon in sequence with a delay, updating the matching HUD
FireAllCannons()<suspends> : void =
# Iterate the CannonTriggers array by index
for (Index -> CannonTrigger : CannonTriggers):
# Fire the cannon trigger (no agent — triggered through code)
CannonTrigger.Trigger()
# Show the matching HUD message if the parallel array has an entry
if (HUD := CannonHUDs[Index]):
# Override the device text at runtime with a dynamic message
HUD.SetText(CannonWarning("CANNON {Index + 1} FIRED — TAKE COVER!"))
HUD.Show()
# Brief pause before the next cannon
Sleep(FireDelay)
# After all cannons have fired, clear every HUD after 3 seconds
Sleep(3.0)
for (HUD : CannonHUDs):
HUD.Hide()
Line-by-line explanation
| Lines | What's happening |
|---|---|
CannonTriggers : []trigger_device |
Declares an editable array of trigger devices. Wire them in the UEFN Details panel. |
CannonHUDs : []hud_message_device |
Parallel array — CannonHUDs[0] belongs to CannonTriggers[0], etc. |
SetMaxTriggerCount(1) |
Caps the crow's-nest trigger to one activation ever. |
TriggeredEvent.Subscribe(OnAlarmRaised) |
Hooks the handler; the event signature is listenable(?agent). |
OnAlarmRaised(MaybeAgent : ?agent) |
Matches the listenable(?agent) signature — we don't need the agent here so we don't unwrap it. |
spawn { FireAllCannons() } |
Launches a suspending function without blocking OnAlarmRaised. |
for (Index -> CannonTrigger : CannonTriggers) |
Index-value iteration: Index is int, CannonTrigger is trigger_device. |
CannonTrigger.Trigger() |
Fires the cannon trigger through code (no agent). |
if (HUD := CannonHUDs[Index]) |
Array indexing is failable — wrap in if to safely access the parallel array. |
HUD.SetText(...) |
Replaces the device's configured text at runtime. |
HUD.Show() |
Displays the message to all players. |
for (HUD : CannonHUDs): HUD.Hide() |
Value-only iteration — no index needed when you just want every element. |
Common patterns
Pattern 1 — Configure every trigger's reset delay from one array
You have a row of dock pressure plates that should reset at different speeds. Store the delays in a parallel []float and iterate both arrays together.
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
dock_plate_configurator := class(creative_device):
@editable
DockPlates : []trigger_device = array{}
# One reset delay (seconds) per plate — must match DockPlates length
@editable
ResetDelays : []float = array{}
OnBegin<override>()<suspends> : void =
# Iterate by index so we can read the matching delay
for (Index -> Plate : DockPlates):
if (Delay := ResetDelays[Index]):
Plate.SetResetDelay(Delay)
# Also enable each plate in case they started disabled
Plate.Enable()
What's new here: SetResetDelay and Enable — two more trigger API calls applied across the whole array in one loop.
Pattern 2 — Show a personalised HUD to a specific agent from a trigger event
When a player steps on the lagoon gate trigger, show them a personal message using Show(Agent, Message) and log how many triggers remain.
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
LagoonGreeting<localizes>(S : string) : message = "{S}"
lagoon_gate_greeter := class(creative_device):
@editable
GateTrigger : trigger_device = trigger_device{}
@editable
WelcomeHUD : hud_message_device = hud_message_device{}
# Array of extra triggers to disable once the gate opens
@editable
SideTriggers : []trigger_device = array{}
OnBegin<override>()<suspends> : void =
GateTrigger.SetMaxTriggerCount(5)
GateTrigger.TriggeredEvent.Subscribe(OnGateTriggered)
OnGateTriggered(MaybeAgent : ?agent) : void =
# Unwrap the optional agent to show a targeted HUD message
if (A := MaybeAgent?):
Remaining := GateTrigger.GetTriggerCountRemaining()
WelcomeHUD.Show(A, LagoonGreeting("Welcome, sailor! {Remaining} entries left."))
# Disable all side triggers — value-only for loop, no index needed
for (Side : SideTriggers):
Side.Disable()
What's new here: GetTriggerCountRemaining() read at runtime, Show(Agent, Message) for a targeted HUD, and the ?agent unwrap pattern with if (A := MaybeAgent?).
Pattern 3 — Clear all HUD messages and re-enable triggers for a new round
At round reset, clear every HUD and re-enable every cannon trigger so the alarm can fire again.
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
cove_round_reset := class(creative_device):
@editable
ResetTrigger : trigger_device = trigger_device{}
@editable
CannonTriggers : []trigger_device = array{}
@editable
CannonHUDs : []hud_message_device = array{}
OnBegin<override>()<suspends> : void =
ResetTrigger.TriggeredEvent.Subscribe(OnRoundReset)
OnRoundReset(MaybeAgent : ?agent) : void =
# Clear all queued HUD messages in one call per device
for (HUD : CannonHUDs):
HUD.ClearAllMessages()
# Re-enable every cannon and reset their trigger count limit
for (Cannon : CannonTriggers):
Cannon.SetMaxTriggerCount(0) # 0 = unlimited
Cannon.Enable()
What's new here: ClearAllMessages() on the HUD device, SetMaxTriggerCount(0) to restore unlimited firing, and Enable() to bring disabled triggers back online.
Gotchas
1. Array indexing is failable — always wrap in if
Writing CannonHUDs[Index] outside a failure context is a compile error. Always use if (HUD := CannonHUDs[Index]): or the access inside a for expression that already handles failure.
2. listenable(?agent) vs listenable(agent)
trigger_device.TriggeredEvent is listenable(?agent) — the agent is optional. Your handler must accept (MaybeAgent : ?agent). If you write (A : agent) the types won't match and the subscribe call won't compile. Unwrap with if (A := MaybeAgent?) before using A as a concrete agent.
3. message is not a string
HUD.SetText() and HUD.Show(Agent, Message) require a message value, not a raw string literal. Declare a <localizes> helper function:
MyText<localizes>(S : string) : message = "{S}"
Then call HUD.SetText(MyText("Fire!")). There is no StringToMessage function.
4. int and float don't auto-convert
SetResetDelay takes float. If you compute a delay as int you must write float(MyInt) to convert it. Passing a bare int literal like 2 works because integer literals are polymorphic, but a variable typed int will not silently coerce.
5. Parallel arrays must stay in sync
If CannonTriggers has 5 elements but CannonHUDs has only 4, CannonHUDs[4] fails silently (the if just skips). Wire all devices in the UEFN Details panel and double-check counts. Consider adding a length-check log in OnBegin during development.
6. spawn is required for suspending work inside an event handler
Event handlers (subscribed methods) are not suspending contexts. If you call Sleep or any <suspends> function directly inside the handler, it won't compile. Wrap the suspending work in spawn { MyFunc() } as shown in the walkthrough.
7. SetMaxTriggerCount clamps to [0, 20]
Passing a value above 20 silently clamps to 20. Use 0 for unlimited. Plan your alarm logic around this ceiling.