Reference Verse compiles

array.Length: Counting Elements to Drive Game Logic

Almost every gameplay system in UEFN eventually asks a simple question: "how many?" How many players are on the team? How many pressure plates are active? How many keys has the squad collected? The `Length` member on any Verse array answers that in one keystroke — and once you can count, you can gate doors, balance teams, and end rounds.

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

Overview

An array is a container that stores elements of the same type — []player, []team, []agent, []button_device, and so on. You get the number of elements in an array by accessing its Length member. For example, array{10, 20, 30}.Length returns 3, and Players.Length tells you how many players are currently in that list.

Length is not a device method — it is a built-in member available on every array in Verse. That makes it the workhorse of counting-based gameplay:

  • Round gating — start a match only when Players.Length >= 2.
  • Team balancing — compare TeamA.Length and TeamB.Length to decide where the next player goes.
  • Collection puzzles — unlock a vault when the collected-keys array reaches a target Length.
  • Elimination win conditions — end the round when a team's living-players array Length hits 0.

Reach for Length whenever your game logic depends on "how many of these do I have right now?". It pairs naturally with the Teams API (GetTeams, GetAgents, GetPlayers) which hand you arrays you can immediately count.

Length returns an int. Remember Verse does not auto-convert int to float, so if you need a float count you must convert explicitly.

API Reference

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

Walkthrough

Let's build a round-start gate. We have a game where players must gather at a lobby. A round should only begin once at least 2 players are present. We read the playspace's player list, count it with .Length, and when we have enough, we unlock a vault door (an barrier_device) and show a message.

using { /Fortnite.com/Devices }
using { /Fortnite.com/Teams }
using { /Fortnite.com/Playspaces }
using { /Fortnite.com/Characters }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/Diagnostics }

round_gate := class(creative_device):

    # The vault door players unlock once enough of them have joined.
    @editable
    VaultDoor : barrier_device = barrier_device{}

    # A HUD message device to announce the count.
    @editable
    Announcer : hud_message_device = hud_message_device{}

    # How many players we need before the round can begin.
    @editable
    RequiredPlayers : int = 2

    # Localized-message helper: a message param needs a localized value, not a raw string.
    CountMessage<localizes>(Have:int, Need:int):message = "Players ready: {Have} / {Need}"

    OnBegin<override>()<suspends>:void =
        # Start with the door blocking the way in.
        VaultDoor.Enable()

        # Re-check the count whenever a player spawns into the world.
        Playspace := GetPlayspace()
        Playspace.PlayerAddedEvent().Subscribe(OnPlayerAdded)

        # Also check once at startup in case players are already here.
        CheckRoundReady()

    # Event handler: fired when a new player joins the playspace.
    OnPlayerAdded(InPlayer:player):void =
        CheckRoundReady()

    # The core counting logic.
    CheckRoundReady():void =
        Players := GetPlayspace().GetPlayers()
        # .Length gives us the current player count as an int.
        Count := Players.Length
        Announcer.SetText(CountMessage(Count, RequiredPlayers))
        Announcer.Show()
        if (Count >= RequiredPlayers):
            # Enough players — drop the barrier so the round can begin.
            VaultDoor.Disable()

Line by line:

  • The @editable fields (VaultDoor, Announcer, RequiredPlayers) let you wire real placed devices and a tunable number in the UEFN details panel. A bare barrier_device{} reference only works because you assign the actual device in the editor.
  • CountMessage<localizes>(...) builds a message — the type SetText expects. There is no StringToMessage; the <localizes> function is how you produce localized text with interpolated {Have} values.
  • In OnBegin, VaultDoor.Enable() turns the barrier ON so it blocks movement.
  • GetPlayspace().PlayerAddedEvent().Subscribe(OnPlayerAdded) wires a handler that runs each time someone joins. Subscribing lives in OnBegin; the handler OnPlayerAdded is a method at class scope.
  • CheckRoundReady() calls GetPlayers() which returns a []player. Players.Length counts them. We compare that int against RequiredPlayers.
  • When the count reaches the threshold we Disable() the barrier, opening the way in.

Common patterns

Team balancing — send the next player to the smaller team

Compare the Length of each team's agent array and route a joining player to whichever side has fewer members.

using { /Fortnite.com/Devices }
using { /Fortnite.com/Teams }
using { /Fortnite.com/Playspaces }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/Diagnostics }

team_balancer := class(creative_device):

    OnBegin<override>()<suspends>:void =
        Playspace := GetPlayspace()
        Playspace.PlayerAddedEvent().Subscribe(OnPlayerAdded)

    OnPlayerAdded(InPlayer:player):void =
        TeamCollection := GetPlayspace().GetTeamCollection()
        Teams := TeamCollection.GetTeams()
        # Need at least two teams to balance between.
        if (TeamA := Teams[0], TeamB := Teams[1]):
            if:
                AgentsA := TeamCollection.GetAgents[TeamA]
                AgentsB := TeamCollection.GetAgents[TeamB]
            then:
                # Whichever team's agent array is shorter gets the new player.
                if (AgentsA.Length <= AgentsB.Length):
                    if (TeamCollection.AddToTeam[InPlayer, TeamA]) {}
                else:
                    if (TeamCollection.AddToTeam[InPlayer, TeamB]) {}

GetTeams() returns []team and GetAgents[Team] returns []agent; comparing their .Length values tells you which side is lighter before AddToTeam places the player.

Elimination win condition — end when a team is empty

Count a team's remaining agents after each elimination; when Length reaches 0, the round is over.

using { /Fortnite.com/Devices }
using { /Fortnite.com/Teams }
using { /Fortnite.com/Playspaces }
using { /Fortnite.com/Characters }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/Diagnostics }

last_team_standing := class(creative_device):

    @editable
    EndGameDevice : end_game_device = end_game_device{}

    OnBegin<override>()<suspends>:void =
        for (P : GetPlayspace().GetPlayers()):
            if (FC := P.GetFortCharacter[]):
                FC.EliminatedEvent().Subscribe(OnEliminated)

    OnEliminated(Result:elimination_result):void =
        TeamCollection := GetPlayspace().GetTeamCollection()
        for (Team : TeamCollection.GetTeams()):
            if (Agents := TeamCollection.GetAgents[Team]):
                # A team with 0 living agents has lost the round.
                if (Agents.Length = 0):
                    EndGameDevice.Activate(Result.EliminatingCharacter)

Here .Length = 0 is the pattern for "is this collection empty?" — a clean win check without manually tracking each elimination.

Collection puzzle — unlock a vault at a target count

Store collected items in a var array, set it as items arrive, and compare Length against the goal.

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

key_collector := class(creative_device):

    @editable
    KeyButtons : []button_device = array{}

    @editable
    Vault : barrier_device = barrier_device{}

    # Which key indices have been pressed so far.
    var CollectedKeys : []int = array{}

    OnBegin<override>()<suspends>:void =
        Vault.Enable()
        for (Index -> Button : KeyButtons):
            Button.InteractedWithEvent.Subscribe(OnKeyPressed)

    OnKeyPressed(Agent:agent):void =
        # Add one key to the collection.
        set CollectedKeys = CollectedKeys + array{CollectedKeys.Length}
        # When we have collected every key, open the vault.
        if (CollectedKeys.Length >= KeyButtons.Length):
            Vault.Disable()

Both the collected array and the source array are counted with .Length, and the puzzle is solved when the two counts match.

Gotchas

  • Length is an int, and Verse never auto-converts to float. If you need Count / 2.0, first convert with IntToFloat(Count) (or Count * 1.0 won't work — use the explicit cast). Comparing two int lengths, as in all the examples above, is fine.
  • Empty check. MyArray.Length = 0 is the idiomatic "is it empty?" test. It does not fail — it evaluates to true/false inside an if.
  • Indexing still fails, Length does not. Players[0] is a failable expression (it fails if the array is empty), so it must live in a failure context. Players.Length always succeeds and returns a plain int — you can read it anywhere.
  • message params need localized values. Devices like hud_message_device.SetText take a message, not a string. Build one with a <localizes> helper (e.g. CountMessage(Count, Need)), never a raw "..." string. There is no StringToMessage.
  • Bracket vs. paren calls. GetAgents, GetTeam, and AddToTeam are <decides> (failable) — call them with square brackets inside an if (TeamCollection.GetAgents[Team]). GetTeams() and GetPlayers() are not failable — call them with parentheses. Mixing these up is a common compile error before you ever get to .Length.
  • Snapshot, not live binding. Players.Length is the count at the moment you read the array. If players join or leave, you must re-read GetPlayers() (as the walkthrough does on PlayerAddedEvent) to get a fresh count.

Build your own lesson with array_length

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 →