Reference Verse compiles

Iterating Arrays in Verse: Light Up the Cove

Your pirate cove has five signal lanterns strung along the dock. When a lookout steps on a pressure plate, every lantern should flash and a HUD message should announce each one in turn. That's the power of array iteration in Verse: one loop, any number of devices, zero copy-paste. This article teaches you how `for` expressions walk arrays and how to wire that loop to real UEFN devices.

Updated Examples verified on the live UEFN compiler
Watch the Knotplayer in ~90 seconds.

Overview

An array in Verse is an ordered, fixed-length sequence of values you can read by index or walk with a for expression. Arrays shine whenever you have N of the same device — lanterns, triggers, spawn pads, HUD messages — and want to act on all of them without writing the same line N times.

Reach for array iteration when:

  • You have a row of triggers, lights, or spawners that should all react to one event.
  • You want to enable/disable a set of devices in sequence.
  • You need to show a series of HUD messages, one per device or player.

The for expression in Verse is the primary tool. It iterates every element and can also expose the zero-based index alongside the element:

for (Item : MyArray):        # element only
for (Index -> Item : MyArray): # index + element

Both forms are used in the examples below.

API Reference

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):

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.

Walkthrough

Scenario — The Cove Lantern Chain

Five trigger_devices are placed along a sun-drenched dock. When a player steps on the harbour pressure plate (a sixth trigger), Verse loops through the lantern triggers and fires each one with a 0.4-second pause between them. A hud_message_device announces each lantern number to every player as it fires.

Place six trigger_devices and one hud_message_device in your UEFN level, then wire them to the script below.

using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }

# Helper: convert a localized template into a message
LanternMsg<localizes>(N : string) : message = "Lantern {N} — signal lit!"

cove_lantern_chain := class(creative_device):

    # The pressure plate on the harbour dock
    @editable
    HarbourPlate : trigger_device = trigger_device{}

    # Five lantern triggers strung along the dock
    @editable
    LanternTriggers : []trigger_device = array{}

    # HUD message device — set to "All Players" in device settings
    @editable
    Announcer : hud_message_device = hud_message_device{}

    OnBegin<override>()<suspends> : void =
        # Subscribe to the harbour plate so stepping on it starts the chain
        HarbourPlate.TriggeredEvent.Subscribe(OnHarbourStepped)

    # Called when a player (or code) fires the harbour plate
    OnHarbourStepped(MaybeAgent : ?agent) : void =
        # Kick off the async lantern sequence on its own task
        spawn { RunLanternSequence() }

    RunLanternSequence()<suspends> : void =
        # Walk every lantern by index so we can show its number
        for (Index -> Lantern : LanternTriggers):
            # Fire the lantern trigger (no agent needed here)
            Lantern.Trigger()

            # Build a human-readable number string (Index is 0-based)
            LanternNumber : string = "{Index + 1}"

            # Show the announcement on every player's HUD
            Announcer.Show(LanternMsg(LanternNumber))

            # Short dramatic pause before the next lantern
            Sleep(0.4)

        # All lanterns lit — clear the HUD after a moment
        Sleep(1.5)
        Announcer.Hide()

Line-by-line explanation

Lines What's happening
@editable HarbourPlate Exposes the pressure-plate trigger in the UEFN details panel so you can drag in the placed device.
@editable LanternTriggers : []trigger_device An editable array of triggers — drag all five lanterns in here.
HarbourPlate.TriggeredEvent.Subscribe(OnHarbourStepped) Registers the handler; fires whenever the plate is stepped on or triggered by code.
OnHarbourStepped(MaybeAgent : ?agent) TriggeredEvent sends ?agent (optional), so the param must be ?agent. We don't need the agent here, so we ignore it.
spawn { RunLanternSequence() } RunLanternSequence calls Sleep, so it must run in its own async task — spawn does that without blocking the event handler.
for (Index -> Lantern : LanternTriggers) Iterates the array; Index is 0, 1, 2 … and Lantern is the trigger_device at that position.
Lantern.Trigger() Fires the lantern trigger with no agent — activates whatever the trigger is linked to in the level (lights, VFX, etc.).
Announcer.Show(LanternMsg(LanternNumber)) Calls the overload Show(Message:message) to push a custom message to all players. LanternMsg is the <localizes> helper that converts a string to message.
Sleep(0.4) Pauses 0.4 seconds before the next iteration — gives the chain a staggered, cinematic feel.
Announcer.Hide() Calls Hide() (no-agent overload) to dismiss the HUD for everyone once the chain is done.

Common patterns

Pattern 1 — Enable a set of triggers all at once

After a round starts you want every dock trap to become active. Loop the array and call Enable() on each.

using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }

dock_trap_activator := class(creative_device):

    @editable
    RoundStartPlate : trigger_device = trigger_device{}

    # All the trap triggers placed along the dock
    @editable
    TrapTriggers : []trigger_device = array{}

    OnBegin<override>()<suspends> : void =
        RoundStartPlate.TriggeredEvent.Subscribe(OnRoundStart)

    OnRoundStart(MaybeAgent : ?agent) : void =
        # Enable every trap trigger in one loop — no copy-paste
        for (Trap : TrapTriggers):
            Trap.Enable()

What's new here: Element-only for (no index needed). Enable() is called on every trigger_device in the array the moment the round-start plate fires.


Pattern 2 — Show a personalised HUD message to each agent in a list

You've collected agents who reached the clifftop beacon. Loop them and show each a personalised message using the agent-specific Show overload.

using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }

BeaconReachedMsg<localizes>(N : string) : message = "Explorer {N}: beacon reached!"

clifftop_beacon_reward := class(creative_device):

    @editable
    BeaconPlate : trigger_device = trigger_device{}

    @editable
    RewardHUD : hud_message_device = hud_message_device{}

    # Agents are collected elsewhere and stored here
    var Explorers : []agent = array{}

    OnBegin<override>()<suspends> : void =
        BeaconPlate.TriggeredEvent.Subscribe(OnBeaconTriggered)

    OnBeaconTriggered(MaybeAgent : ?agent) : void =
        # If a real agent triggered it, add them to the list
        if (A := MaybeAgent?):
            set Explorers = Explorers + array{A}
        spawn { AnnounceExplorers() }

    AnnounceExplorers()<suspends> : void =
        for (Index -> Explorer : Explorers):
            # Show a custom message to THIS specific agent only
            NumberStr : string = "{Index + 1}"
            RewardHUD.Show(Explorer, BeaconReachedMsg(NumberStr))
            Sleep(0.3)

What's new here: Show(Agent:agent, Message:message) targets one player at a time. The ?agent from TriggeredEvent is unwrapped with if (A := MaybeAgent?) before use.


Pattern 3 — Limit and stagger triggers with SetMaxTriggerCount and SetResetDelay

Before the cove defence begins, configure each trap trigger so it can only fire twice and must wait 2 seconds between activations.

using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }

cove_trap_configurator := class(creative_device):

    @editable
    ConfigPlate : trigger_device = trigger_device{}

    @editable
    TrapTriggers : []trigger_device = array{}

    @editable
    StatusHUD : hud_message_device = hud_message_device{}

    ConfiguredMsg<localizes>() : message = "Traps armed — 2 shots each!"

    OnBegin<override>()<suspends> : void =
        ConfigPlate.TriggeredEvent.Subscribe(OnConfigRequested)

    OnConfigRequested(MaybeAgent : ?agent) : void =
        for (Trap : TrapTriggers):
            # Each trap may only fire twice
            Trap.SetMaxTriggerCount(2)
            # Must wait 2 seconds before it can fire again
            Trap.SetResetDelay(2.0)

        # Confirm to all players
        StatusHUD.Show(ConfiguredMsg())

        # Auto-hide after 3 seconds
        spawn { HideAfterDelay() }

    HideAfterDelay()<suspends> : void =
        Sleep(3.0)
        StatusHUD.Hide()

What's new here: SetMaxTriggerCount(2) and SetResetDelay(2.0) are called inside the loop, configuring every trap in one pass. StatusHUD.Show(ConfiguredMsg()) uses the no-agent overload to broadcast to all players.

Gotchas

1. for in Verse is an expression, not a statement — it can fail silently on an empty array. If LanternTriggers is empty (you forgot to assign devices in the details panel), the for body never runs and no error is thrown. Always test with at least one element assigned.

2. @editable arrays must be populated in the UEFN Details panel. Declaring LanternTriggers : []trigger_device = array{} gives you an empty array at runtime unless you drag devices into the slot. The default array{} is just the fallback — it is not auto-populated.

3. TriggeredEvent sends ?agent, not agent. The handler signature must be (MaybeAgent : ?agent). If you write (A : agent) the subscription will fail to compile. Always unwrap with if (A := MaybeAgent?): before passing the agent to device methods that require a concrete agent.

4. message is not a string. Device methods like SetText and Show(Message:message) require a message value, not a plain string. Use a <localizes> helper function (e.g. MyMsg<localizes>(S:string):message = "{S}") to convert. There is no StringToMessage function.

5. Async calls inside for loops need spawn or a <suspends> context. Sleep() is <suspends>, so calling it inside a for loop is only legal if the enclosing function is also <suspends>. Event handlers are not <suspends>, so always delegate to a helper via spawn { MyAsyncFunc() }.

6. Index in for (Index -> Item : Array) is zero-based. The first element is at index 0. If you display it to players, add 1: "{Index + 1}".

7. Verse does not auto-convert int to float. SetResetDelay takes a float. Write 2.0, not 2. Passing an int literal where a float is expected is a compile error.

Guides & scripts that use player

Step-by-step tutorials that put this object to work.

Build your own lesson with player

Generate a personalized, step-by-step lesson plan built around this object — grounded in this exact reference and our compile-verified knowledge base.

Build a lesson →