Reference Devices

volume_device: Tracking Who's Inside a Space

The volume_device is your invisible tripwire: a 3D region that fires events the moment a player or prop crosses its boundary. Use it to build vault rooms, capture zones, safe areas, and trap triggers — all in clean, readable Verse.

Updated
The code on this reference page is provided as-is and did not pass the latest compile check — treat the examples as a starting point and verify in your project.
Watch the Knotvolume_device in ~90 seconds.

Overview

The volume_device defines an invisible 3D region in your island and tells you exactly who and what is inside it. Unlike a trigger that fires on a single touch, a volume tracks continuous occupancy — it signals when an agent enters and again when they exit, and it can report the full list of agents currently standing inside at any moment.

Reach for the volume_device when you need to answer questions like:

  • Is the player standing in the vault room right now?
  • How many players are inside the capture zone (so I can score a team)?
  • Did a physics prop get knocked into the lava pit?
  • Has every defender left the safe area?

It exposes four events — AgentEntersEvent, AgentExitsEvent, PropEnterEvent, PropExitEvent — and two query methods — GetAgentsInVolume() and IsInVolume(). Because the events are listenable(agent) (and listenable(creative_prop)), your handler receives the thing that crossed the boundary, so you can act on that specific player or prop.

API Reference

volume_device

Used to track when agents enter and exit a volume.

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

volume_device<public> := class<concrete><final>(creative_device_base):

Events (subscribe a handler to react):

Event Signature Description
AgentEntersEvent AgentEntersEvent<public>:listenable(agent) Signaled when an agent enters the device volume.
AgentExitsEvent AgentExitsEvent<public>:listenable(agent) Signaled when an agent exits the device volume.
PropEnterEvent PropEnterEvent<public>:listenable(creative_prop) Signaled when an creative_prop entered the device volume.
PropExitEvent PropExitEvent<public>:listenable(creative_prop) Signaled when an creative_prop exited the device volume.

Methods (call these to make the device act):

Method Signature Description
GetAgentsInVolume GetAgentsInVolume<public>()<reads>:[]agent Returns an array of agents that are currently occupying the volume.
IsInVolume IsInVolume<public>(Agent:agent)<transacts><decides>:void Succeeds when Agent is in the volume.

Walkthrough

Let's build a vault room. A volume covers the room. The moment a player steps inside, we start a 10-second "alarm" countdown and grant them on-screen warnings. If they leave before the timer ends, the alarm cancels. We'll use AgentEntersEvent to start, AgentExitsEvent to cancel, and GetAgentsInVolume() to confirm the room is empty before resetting.

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

vault_log := class(log_channel){}

# Helper turning a plain string into the localized `message` type the UI wants.
VaultText<localizes>(S:string):message = "{S}"

vault_room_device := class(creative_device):
    Logger:log = log{Channel := vault_log}

    # The volume covering the vault room. Drag your placed Volume here in the Details panel.
    @editable
    VaultVolume:volume_device = volume_device{}

    # Track whether the alarm coroutine should keep running.
    var AlarmActive:logic = false

    OnBegin<override>()<suspends>:void =
        # React when anyone crosses into or out of the room.
        VaultVolume.AgentEntersEvent.Subscribe(OnAgentEntered)
        VaultVolume.AgentExitsEvent.Subscribe(OnAgentExited)

    OnAgentEntered(Agent:agent):void =
        Logger.Print("An agent entered the vault.")
        ShowMessage(Agent, VaultText("Vault breach detected! Alarm in 10s..."))
        set AlarmActive = true
        spawn{ RunAlarm() }

    OnAgentExited(Agent:agent):void =
        Logger.Print("An agent left the vault.")
        # Only cancel the alarm if the room is now completely empty.
        Occupants := VaultVolume.GetAgentsInVolume()
        if (Occupants.Length = 0):
            set AlarmActive = false
            ShowMessage(Agent, VaultText("Vault secured. Alarm cancelled."))

    RunAlarm()<suspends>:void =
        Sleep(10.0)
        # If nobody cancelled it, the heist succeeds.
        if (AlarmActive?):
            Logger.Print("ALARM! Vault stayed breached for 10 seconds.")
            for (A : VaultVolume.GetAgentsInVolume()):
                ShowMessage(A, VaultText("Heist complete!"))

    ShowMessage(Agent:agent, Msg:message):void =
        if (Player := player[Agent], PC := Player.GetControllerInterface[]):
            # GetControllerInterface gives a playspace UI hook; fall back to logging.
            Logger.Print("Message shown to a player.")

Line by line:

  • vault_log := class(log_channel){} declares a log channel so our Logger.Print output is tagged.
  • VaultText<localizes>(S:string):message is the required pattern for producing a message value — UI APIs never take a raw string. There is no StringToMessage.
  • @editable VaultVolume:volume_device is the field that lets us call the placed device. Without an @editable field inside a creative_device class, VaultVolume.AgentEntersEvent would fail with "Unknown identifier."
  • In OnBegin, we Subscribe two handlers. AgentEntersEvent is listenable(agent), so the handler signature is (Agent:agent):void — already unwrapped, no ? needed here because the type is the non-optional agent.
  • OnAgentEntered flips AlarmActive to true and spawns the countdown coroutine so it runs concurrently without blocking the event handler.
  • OnAgentExited calls GetAgentsInVolume() and checks .Length = 0. This is the key trick: the exit event fires per-agent, so we must re-query the volume to know if the room is truly empty before cancelling.
  • RunAlarm sleeps 10 seconds, then re-checks AlarmActive? (the logic unwrap) before declaring the heist a success.

Common patterns

Use IsInVolume to gate an interaction

IsInVolume(Agent) is a <decides> query — it succeeds only when that agent is inside. Perfect for "you must be standing in the zone to do X" checks.

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

zone_check_log := class(log_channel){}

zone_gate_device := class(creative_device):
    Logger:log = log{Channel := zone_check_log}

    @editable
    CaptureZone:volume_device = volume_device{}

    @editable
    ScoreButton:button_device = button_device{}

    OnBegin<override>()<suspends>:void =
        ScoreButton.InteractedWithEvent.Subscribe(OnButtonPressed)

    OnButtonPressed(Agent:agent):void =
        # Only award the point if the presser is actually inside the capture zone.
        if (CaptureZone.IsInVolume[Agent]):
            Logger.Print("Point scored — agent was in the zone.")
        else:
            Logger.Print("Press ignored — agent is outside the zone.")

Count occupants for team-scoring

GetAgentsInVolume() returns the live array of agents inside — ideal for periodically tallying how many players hold a point.

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

tally_log := class(log_channel){}

zone_tally_device := class(creative_device):
    Logger:log = log{Channel := tally_log}

    @editable
    PointVolume:volume_device = volume_device{}

    OnBegin<override>()<suspends>:void =
        # Every 5 seconds, count who's holding the point.
        loop:
            Sleep(5.0)
            Occupants := PointVolume.GetAgentsInVolume()
            Count := Occupants.Length
            if (Count > 0):
                Logger.Print("Point contested by some players.")
            else:
                Logger.Print("Point is empty.")

React to props entering a volume

PropEnterEvent and PropExitEvent track creative_props — useful for a "knock the barrel into the pit" puzzle. The handler receives the prop, so you can hide or dispose it.

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

pit_log := class(log_channel){}

prop_pit_device := class(creative_device):
    Logger:log = log{Channel := pit_log}

    @editable
    PitVolume:volume_device = volume_device{}

    OnBegin<override>()<suspends>:void =
        PitVolume.PropEnterEvent.Subscribe(OnPropFell)
        PitVolume.PropExitEvent.Subscribe(OnPropLeft)

    OnPropFell(Prop:creative_prop):void =
        Logger.Print("A prop fell into the pit — removing it.")
        # Make the prop vanish (disables collision) once it's in the pit.
        Prop.Hide()

    OnPropLeft(Prop:creative_prop):void =
        Logger.Print("A prop left the pit volume.")

Gotchas

  • @editable field is mandatory. You cannot call volume_device{}.AgentEntersEvent on a freshly-constructed value — that empty instance isn't your placed device. Declare @editable VaultVolume:volume_device = volume_device{}, then assign the placed device in the Details panel.
  • Exit fires per-agent, not per-room. When two players are inside and one leaves, AgentExitsEvent fires once. To know whether the room is empty, call GetAgentsInVolume() and check .Length = 0 — don't assume an exit means empty.
  • IsInVolume is a <decides> function. Call it with square brackets inside an if (if (Vol.IsInVolume[Agent]):), not round parentheses. It returns no value — its success/failure is the answer.
  • agent handlers are already unwrapped. AgentEntersEvent is listenable(agent) (non-optional), so the handler param is Agent:agent and you use it directly. You only need the if (A := Agent?) unwrap when an event hands you an optional ?agent.
  • message needs the localized helper. Any UI text param wants a message, produced by a <localizes> function like VaultText. Passing a raw "string" will not compile.
  • Props are creative_prop, not agent. Don't try to feed a prop from PropEnterEvent into GetAgentsInVolume-style agent logic — they're different types with different events.

Device Settings & Options

The volume_device User Options panel in the UEFN editor — every setting you can tune.

Volume Device settings and options panel in the UEFN editor — Visible in Game, Volume Width, Volume Depth, Volume Height, Volume Radius, Player Events Enabled
Volume Device — User Options in the UEFN editor: Visible in Game, Volume Width, Volume Depth, Volume Height, Volume Radius, Player Events Enabled
⚙️ Settings on this device (6)

Setting names read from the panel above — may be partial; the screenshots are the source of truth.

Visible in Game
Volume Width
Volume Depth
Volume Height
Volume Radius
Player Events Enabled

Guides & scripts that use volume_device

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

Build your own lesson with volume_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 →