Reference Verse compiles

vector3: Charting the Cove — Positions, Distances, and Directions in Verse

Every chest on a pirate dock, every wave-lapped rock in a cove, every plank on a sun-bleached pier lives at a precise point in 3D space — and in Verse that point is a vector3. This article teaches you what vector3 is, how its X/Y/Z fields work, and how to use it alongside real devices to build position-aware gameplay on your cel-shaded island.

Updated Examples verified on the live UEFN compiler

Overview

A vector3 is a plain Verse struct with three float fields — X, Y, and Z — that together describe a point or direction in 3D space. Because it is a struct (a value type), you can create one anywhere with a struct literal, pass it around freely, and compare two of them field-by-field without worrying about references or ownership.

In UEFN, world coordinates use centimetres: positive X points forward (north on most islands), positive Y points right (east), and positive Z points up. A dock plank sitting 10 metres ahead of the spawn would be roughly at vector3{X := 1000.0, Y := 0.0, Z := 0.0}.

When to reach for vector3:

  • Storing a landmark position (the cove entrance, the treasure chest, the clifftop cannon).
  • Calculating the distance between two world points so you can trigger events when a player is "close enough".
  • Building a direction vector to aim a projectile, push a character, or orient a prop.
  • Passing a force or impulse to fort_character.ApplyForce / ApplyLinearImpulse.

vector3 has no methods of its own — you work with it through arithmetic operators (+, -, *) and the SpatialMath helpers (Distance, Normalize, etc.) that the engine exposes on vectors. The power is in combining those simple operations with device events.

API Reference

vector3

3-dimensional vector with float components.

Full public surface, resolved verbatim from the live Epic digest (Verse.digest.verse).

vector3<native><public> := struct<concrete><computes><persistable><uht_comparable>:

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 Proximity Alert

Your cel-shaded island has a hidden lagoon cove. A trigger_device marks the entrance. When any player fires that trigger, your Verse device:

  1. Reads the triggering agent's world position.
  2. Computes the vector from the player to the cove's treasure chest landmark.
  3. Displays a personalised HUD message that tells the player how far away the chest is (in metres).

Place in your level:

  • EntranceTrigger — a trigger_device at the cove mouth.
  • ChestHUD — a hud_message_device set to Target Specific Agent.
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /Fortnite.com/Characters }
using { /UnrealEngine.com/Temporary/SpatialMath }

# Localised message helper — required because hud_message_device.Show takes `message`, not `string`.
DistanceMsg<localizes>(S : string) : message = "{S}"

cove_proximity_device := class(creative_device):

    # ── Editable device references ──────────────────────────────────────────
    @editable
    EntranceTrigger : trigger_device = trigger_device{}

    @editable
    ChestHUD : hud_message_device = hud_message_device{}

    # The world position of the treasure chest landmark (set this to match
    # where you placed your chest prop in the level — values in centimetres).
    ChestPosition : vector3 = vector3{X := 3200.0, Y := -800.0, Z := 50.0}

    # ── Lifecycle ───────────────────────────────────────────────────────────
    OnBegin<override>()<suspends> : void =
        # Subscribe to the trigger so we react whenever a player enters the cove.
        EntranceTrigger.TriggeredEvent.Subscribe(OnPlayerEnteredCove)

        # Allow the trigger to fire unlimited times (one per player visit).
        EntranceTrigger.SetMaxTriggerCount(0)

        # Small reset delay so rapid re-entries don't spam the HUD.
        EntranceTrigger.SetResetDelay(3.0)

    # ── Event handler ───────────────────────────────────────────────────────
    # TriggeredEvent sends ?agent, so the parameter is optional.
    OnPlayerEnteredCove(MaybeAgent : ?agent) : void =
        if (Agent := MaybeAgent?):
            # Get the player's current world position via the fort_character interface.
            if (Character := Agent.GetFortCharacter[]):
                PlayerPos : vector3 = Character.GetTransform().Translation

                # Build the offset vector from player to chest.
                Offset : vector3 = vector3
                {
                    X := ChestPosition.X - PlayerPos.X
                    Y := ChestPosition.Y - PlayerPos.Y
                    Z := ChestPosition.Z - PlayerPos.Z
                }

                # Distance = magnitude of the offset vector (Pythagorean theorem).
                DistanceCm : float =
                    Sqrt(Offset.X * Offset.X + Offset.Y * Offset.Y + Offset.Z * Offset.Z)

                # Convert centimetres → metres for a friendly display value.
                DistanceM : float = DistanceCm / 100.0

                # Round to one decimal place for readability.
                DistanceText : string = "{DistanceM}"

                # Show the personalised message on this player's HUD.
                ChestHUD.Show(Agent, DistanceMsg("🏴‍☠️ Treasure chest is {DistanceText} m away!"), ?DisplayTime := 4.0)```

### Line-by-line explanation

| Lines | What's happening |
|---|---|
| `ChestPosition : vector3 = vector3{X := …}` | A struct literal creates an immutable landmark position. All three fields are `float` — never `int`. |
| `EntranceTrigger.SetMaxTriggerCount(0)` | `0` means unlimited triggers — every player who enters gets a message. |
| `EntranceTrigger.SetResetDelay(3.0)` | Prevents the same player from spamming the trigger within 3 seconds. |
| `OnPlayerEnteredCove(MaybeAgent : ?agent)` | `TriggeredEvent` is `listenable(?agent)` — the payload is **optional**, so the parameter type is `?agent`. |
| `if (Agent := MaybeAgent?)` | Unwrap the option. If no agent triggered it (e.g. triggered via code), we skip gracefully. |
| `Character.GetTransform().Translation` | Returns a `vector3` — the character's world position in centimetres. |
| `Offset : vector3 = vector3{X :=  Y :=  Z := }` | Manual component subtraction builds the displacement vector. |
| `Sqrt(Offset.X * Offset.X + )` | Classic Euclidean distance formula  `vector3` has no `.Length()` method, so we compute it ourselves. |
| `DistanceCm / 100.0` | Verse does **not** auto-convert `int` to `float`, so we divide by the float literal `100.0`. |
| `ChestHUD.Show(Agent, DistanceMsg(), ?DisplayTime := 4.0)` | The three-argument `Show` overload targets a specific agent with a custom `message` and display time. |

## Common patterns

### Pattern 1 — Comparing two landmark vectors to pick the nearer one

You have two coves. When the player triggers the dock trigger, show which cove is closer.

```verse
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /Verse.org/SpatialMath }
using { /UnrealEngine.com/Temporary/SpatialMath }

NearerMsg<localizes>(S : string) : message = "{S}"

two_coves_device := class(creative_device):

    @editable
    DockTrigger : trigger_device = trigger_device{}

    @editable
    InfoHUD : hud_message_device = hud_message_device{}

    # Two landmark positions in world-space centimetres.
    NorthCove : vector3 = vector3{X := 5000.0, Y :=  1000.0, Z := 0.0}
    SouthCove : vector3 = vector3{X := -4000.0, Y := -500.0,  Z := 0.0}

    OnBegin<override>()<suspends> : void =
        DockTrigger.TriggeredEvent.Subscribe(OnDockTriggered)

    OnDockTriggered(MaybeAgent : ?agent) : void =
        if (Agent := MaybeAgent?):
            if (Char := Agent.GetFortCharacter[]):
                Pos : vector3 = Char.GetTransform().Translation

                # Squared distances — avoids a Sqrt when we only need to compare.
                NorthDx : float = NorthCove.X - Pos.X
                NorthDy : float = NorthCove.Y - Pos.Y
                NorthDz : float = NorthCove.Z - Pos.Z
                NorthSq : float = NorthDx * NorthDx + NorthDy * NorthDy + NorthDz * NorthDz

                SouthDx : float = SouthCove.X - Pos.X
                SouthDy : float = SouthCove.Y - Pos.Y
                SouthDz : float = SouthCove.Z - Pos.Z
                SouthSq : float = SouthDx * SouthDx + SouthDy * SouthDy + SouthDz * SouthDz

                if (NorthSq < SouthSq):
                    InfoHUD.Show(Agent, NearerMsg("⚓ North Cove is closer!"), ?DisplayTime := 3.0)
                else:
                    InfoHUD.Show(Agent, NearerMsg("⚓ South Cove is closer!"), ?DisplayTime := 3.0)

Key idea: Comparing squared distances is cheaper than comparing real distances because you skip two Sqrt calls. Only convert to real distance when you need the actual number.


Pattern 2 — Using vector3 components to build a height-based HUD warning

The Z component alone tells you altitude. Warn players who stray above the clifftop safety line.

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

HeightMsg<localizes>(S : string) : message = "{S}"

clifftop_guard_device := class(creative_device):

    @editable
    CliffTrigger : trigger_device = trigger_device{}

    @editable
    WarningHUD : hud_message_device = hud_message_device{}

    # Any Z above this value (in cm) is "too high" — 2000 cm = 20 m.
    DangerAltitudeCm : float = 2000.0

    OnBegin<override>()<suspends> : void =
        CliffTrigger.TriggeredEvent.Subscribe(OnCliffTriggered)
        # Let the trigger fire at most 5 times total, then disable itself.
        CliffTrigger.SetMaxTriggerCount(5)

    OnCliffTriggered(MaybeAgent : ?agent) : void =
        if (Agent := MaybeAgent?):
            if (Char := Agent.GetFortCharacter[]):
                # Pull just the Z component — we don't need X or Y here.
                PlayerZ : float = Char.GetTransform().Translation.Z

                if (PlayerZ > DangerAltitudeCm):
                    AltM : float = PlayerZ / 100.0
                    WarningHUD.Show(Agent, HeightMsg("⚠️ Too high! Altitude: {AltM} m"), ?DisplayTime := 5.0)
                else:
                    WarningHUD.Show(Agent, HeightMsg("✅ Safe altitude."), ?DisplayTime := 2.0)

                # Check remaining triggers and log to HUD if almost exhausted.
                Remaining : int = CliffTrigger.GetTriggerCountRemaining()
                if (Remaining = 1):
                    WarningHUD.Show(HeightMsg("🔔 Cliff sensor almost used up!"))

Key idea: You can read individual fields (Translation.Z) without constructing a new vector3. GetTriggerCountRemaining() lets you react when a trigger is nearly spent.


Pattern 3 — Programmatically triggering a device and clearing HUD messages

Sometimes you want to fire a trigger from code (not from a player stepping on it) and then wipe all HUD messages when the scene resets.

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

ResetMsg<localizes>(S : string) : message = "{S}"

lagoon_reset_device := class(creative_device):

    @editable
    ResetTrigger : trigger_device = trigger_device{}

    @editable
    StatusHUD : hud_message_device = hud_message_device{}

    # The "reset beacon" world position — a buoy in the lagoon centre.
    BuoyPosition : vector3 = vector3{X := 0.0, Y := 0.0, Z := 100.0}

    OnBegin<override>()<suspends> : void =
        ResetTrigger.TriggeredEvent.Subscribe(OnReset)

        # Show a persistent startup message (DisplayTime 0.0 = forever).
        StatusHUD.Show(ResetMsg("🌊 Lagoon active — find the buoy!"), ?DisplayTime := 0.0)

        # Wait 30 seconds, then fire the reset trigger programmatically.
        Sleep(30.0)
        ResetTrigger.Trigger()   # No agent — code-initiated trigger.

    OnReset(MaybeAgent : ?agent) : void =
        # Clear every queued HUD message for all players.
        StatusHUD.ClearAllMessages()

        # Announce the buoy coordinates on the global HUD.
        BuoyX : float = BuoyPosition.X / 100.0
        BuoyY : float = BuoyPosition.Y / 100.0
        StatusHUD.Show(ResetMsg("🔄 Scene reset! Buoy at ({BuoyX} m, {BuoyY} m)"), ?DisplayTime := 6.0)

        # Disable the trigger so it can't fire again until re-enabled.
        ResetTrigger.Disable()

Key idea: Trigger() (no arguments) fires the device from code — TriggeredEvent will send false/none for the agent, which is why unwrapping ?agent safely handles both cases. ClearAllMessages() wipes every player's queue at once.

Gotchas

1. All three fields are float — never int

# ✅ Correct
MyPos : vector3 = vector3{X := 100.0, Y := 0.0, Z := 50.0}

# ❌ Compile error — int literal where float expected
# MyPos : vector3 = vector3{X := 100, Y := 0, Z := 50}

Verse does not auto-promote int to float. Always write the decimal point.


2. vector3 has no built-in .Length() or .Distance() — compute it yourself

The struct exposes only X, Y, Z. There is no .Magnitude() method on the struct itself. Use the Pythagorean formula or the SpatialMath module helpers (Distance(), Normalize()) which operate on vectors from the /Verse.org/SpatialMath namespace.


3. TriggeredEvent is listenable(?agent) — always unwrap

# Handler signature MUST match listenable(?agent)
OnTriggered(MaybeAgent : ?agent) : void =
    if (Agent := MaybeAgent?):   # ← unwrap before use
        # safe to use Agent here

If you write (Agent : agent) instead of (MaybeAgent : ?agent) the subscription will fail to compile because the types don't match.


4. messagestring — you need a <localizes> wrapper

hud_message_device.Show(Agent, …) and SetText(…) both take message, not string. Raw string literals are not message. Always declare a localisation helper:

MyLabel<localizes>(S : string) : message = "{S}"
# Then call:
HUD.Show(Agent, MyLabel("Hello cove!"))

There is no StringToMessage function in Verse.


5. SetMaxTriggerCount clamps to [0, 20]

Values above 20 are silently clamped to 20. Use 0 for unlimited. If you need more than 20 discrete firings, reset the count programmatically by calling Enable() after the device exhausts itself.


6. Indentation is semantic in Verse

Verse uses 4-space indentation as block delimiters — braces do not define scope. A misindented if body or handler method will produce cryptic parse errors. Keep every class field and method at exactly 4 spaces, and every statement inside a method body at 8 spaces (or more for nested blocks).

Guides & scripts that use vector3

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

Build your own lesson with vector3

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 →