Reference Verse compiles

for with index: Looping Over Devices on the Pirate Cove

You dropped five glowing pressure plates along the sunny cove and one countdown timer on the pirate ship — now you need to arm them all in one clean loop. Verse's `for` expression with an index lets you walk an array element-by-element while knowing exactly which position you're on, so plate #0 gets a fast reset and plate #4 gets a slow one. This article teaches `for ... with index` through real `trigger_device` and `timer_device` calls.

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

Overview

Picture a bright, cel-shaded cove: three teleporter pads sit in a neat row along the dock, and you want to light them up one after another — pad 0 first, then pad 1, then pad 2 — awarding a little more score for each pad the player reaches. A regular for (Pad : Pads) walks the array but never tells you where you are. That's the whole problem for-with-index solves.

for-with-index is not a device — it's a core Verse loop form. When you iterate an array, you can ask for the position alongside the element:

for (Index -> Value : MyArray):
    # Index is a zero-based int, Value is the element

Reach for it whenever the order matters: staggering delays, numbering players on a leaderboard, activating device number N, or granting points that scale with position. Because @editable []device fields let you drop a whole row of pads or scoreboards into one array in the UEFN details panel, for-with-index becomes the natural way to drive them all from one script.

API Reference

(API surface could not be resolved for this device.)

Walkthrough

Here's the full cove moment. A row of teleporter_devices and a matching row of score_manager_devices are wired into two arrays. When a player steps into the first teleporter, we loop the whole row with index: each teleporter links to its target, and each score manager is told to grant Index + 1 points (pad 0 → 1 point, pad 1 → 2 points, pad 2 → 3 points) by calling Increment that many times before Activate.

using { /Fortnite.com/Devices }
using { /UnrealEngine.com/Temporary/UI }
using { /Verse.org/Simulation }

cove_relay := class(creative_device):

    # A row of teleporter pads dropped along the dock.
    @editable
    Teleporters : []teleporter_device = array{}

    # A matching row of score managers, one per pad.
    @editable
    Scorers : []score_manager_device = array{}

    # The pad the player steps into to kick everything off.
    @editable
    StartPad : teleporter_device = teleporter_device{}

    OnBegin<override>()<suspends>:void =
        # When someone enters the start pad, run the staggered activation.
        StartPad.EnterEvent.Subscribe(OnPlayerArrived)

    OnPlayerArrived(Agent : agent):void =
        # Walk the teleporter row WITH its index.
        for (Index -> Pad : Teleporters):
            # Every pad links back so the player can return.
            Pad.ActivateLinkToTarget()

            # Award points that scale with the pad's position.
            # Pad 0 gives 1 point, pad 1 gives 2, pad 2 gives 3...
            if (Scorer := Scorers[Index]):
                # Increment (Index + 1) times so the next Activate grants that many.
                for (Bump := 0..Index):
                    Scorer.Increment(Agent)
                Scorer.Activate(Agent)

Line by line:

  • @editable Teleporters : []teleporter_device = array{} declares an array field. In UEFN you drop each dock pad into a slot; the order in the panel becomes the index order here.
  • StartPad.EnterEvent.Subscribe(OnPlayerArrived) wires the trigger. EnterEvent is a listenable(agent), so the handler receives an agent directly.
  • for (Index -> Pad : Teleporters): is the star. Index is a zero-based int; Pad is the teleporter_device at that position. Both are available in one loop.
  • Pad.ActivateLinkToTarget() calls a real teleporter method on each pad so it can return the player later.
  • if (Scorer := Scorers[Index]): indexes the parallel array. Array indexing can fail (out of bounds), so it must be guarded with if — this fails gracefully if the two rows aren't the same length.
  • for (Bump := 0..Index): Scorer.Increment(Agent) uses the index as a count: it bumps the pending score by 1 for each step from 0 through Index, so higher pads award more.
  • Scorer.Activate(Agent) grants the accumulated points to the player.

Common patterns

Staggered cinematics — play sequence N after N seconds. The index becomes a delay, so a row of cinematic devices fires like a wave rolling down the shore.

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

wave_cinematics := class(creative_device):

    @editable
    Sequences : []cinematic_sequence_device = array{}

    @editable
    Kickoff : teleporter_device = teleporter_device{}

    OnBegin<override>()<suspends>:void =
        Kickoff.EnterEvent.Subscribe(OnStart)

    OnStart(Agent : agent):void =
        spawn { PlayWave() }

    PlayWave()<suspends>:void =
        # Index gives each sequence its own delay before playing.
        for (Index -> Seq : Sequences):
            Sleep(Index * 1.0)
            Seq.Play()

Numbering a spawn line — spawn player N from spawner N. Loop players and spawners together, matching each player to the pad at the same index.

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

spawn_line := class(creative_device):

    @editable
    Spawners : []player_spawner_device = array{}

    @editable
    GoPad : teleporter_device = teleporter_device{}

    OnBegin<override>()<suspends>:void =
        GoPad.EnterEvent.Subscribe(OnGo)

    OnGo(Agent : agent):void =
        Players := GetPlayspace().GetPlayers()
        # Pair each player with the spawner at the same slot.
        for (Index -> P : Players):
            if (Spawner := Spawners[Index], FortP := player[P]):
                Spawner.SpawnPlayer(FortP)

Resetting a row of timers with a position-based label. Here the index just proves we visited each element in order while calling a real device method on each.

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

timer_row := class(creative_device):

    @editable
    Timers : []timer_device = array{}

    @editable
    ResetPad : teleporter_device = teleporter_device{}

    OnBegin<override>()<suspends>:void =
        ResetPad.EnterEvent.Subscribe(OnReset)

    OnReset(Agent : agent):void =
        for (Index -> T : Timers):
            # First timer resets for the agent; the rest reset for all.
            if (Index = 0):
                T.Reset(Agent)
            else:
                T.ResetForAll()

Gotchas

  • Indexing a parallel array can fail. Scorers[Index] is a failable expression — if Scorers is shorter than Teleporters, it fails. Always guard with if (Scorer := Scorers[Index]):. Never assume two @editable arrays are the same length; a designer can leave a slot empty.
  • The index is always an int, and Verse won't auto-convert. If you want to use it as a float delay (Sleep), you must multiply by a float: Index * 1.0, not Index. Mixing int and float is a compile error.
  • Index -> Value order matters. The name before the arrow is the index/key; the name after is the value. Writing for (Pad -> Index : Teleporters) silently gives you an int where you expected a device — the compiler will complain when you call a device method on it.
  • EnterEvent hands you an agent, not a player. Methods like SpawnPlayer need a player, so unwrap with if (FortP := player[P]): before calling them. Don't force the raw agent in.
  • The loop body is a normal method, not a suspending context. If you need Sleep between iterations (staggered waves), the loop must run inside a <suspends> function that you spawn, as in the cinematics pattern — you can't Sleep directly inside a plain event handler.
  • Zero-based indexing. The first element is Index = 0. If you want human-friendly 'Pad 1, Pad 2', add 1 when you display or count — that's exactly why the walkthrough grants Index + 1 points.

Guides & scripts that use trigger_device

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

Build your own lesson with trigger_device

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 →