Reference Verse compiles

Using a Module: Sharing Verse Code Across Your Cove

Every Verse file starts with `using { ... }` lines — those are you importing MODULES. A module is a named bundle of code (types, devices, helpers) that lives at a path like `/Fortnite.com/Devices`. On a bright cel-shaded pirate cove, we'll wire a stepping-plate trigger to a treasure-timer using nothing but the modules Epic ships — and then build our OWN little module to share helper code between devices.

Updated Examples verified on the live UEFN compiler

Overview

When you write Verse for UEFN, the very first lines of every file look like this:

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

Each using line imports a module — a named, path-addressed bundle of code owned by someone (Fortnite.com, Verse.org, or you). Without the right using, the names you need (trigger_device, timer_device, Subscribe) don't exist in your scope and the compiler reports 'Unknown identifier'. That is the #1 beginner error, and it's always a missing using.

Modules solve a real game problem: code organization and reuse. Say your pirate cove has three devices that all need to "reward the player who reached the treasure" the same way. Instead of copy-pasting that logic three times, you put it in one module and using it from each device. Reach for modules when:

  • You need a symbol from Epic's libraries (devices, math, UI) — you using their module.
  • You want to share helper functions/types between your own scripts — you author your own module.

This article teaches both: importing the standard modules to make a trigger_device start a timer_device, then factoring shared helpers into your own module.

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.

timer_device

Provides a way to keep track of the time something has taken, either for scoreboard purposes, or to trigger actions. It can be configured in several ways, either acting as a countdown to an event that is triggered at the end, or as a stopwatch for an action that needs to be completed before a set time runs out.

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

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

Events (subscribe a handler to react):

Event Signature Description
SuccessEvent SuccessEvent<public>:listenable(?agent) Signaled when the timer completes or ends with success. Sends the agent that activated the timer, if any.
FailureEvent FailureEvent<public>:listenable(?agent) Signaled when the timer completes or ends with failure. Sends the agent that activated the timer, if any.
StartUrgencyModeEvent StartUrgencyModeEvent<public>:listenable(?agent) Signaled when the timer enters Urgency Mode. Sends the agent that activated the timer, if any.

Methods (call these to make the device act):

Method Signature Description
Enable Enable<public>(Agent:agent):void Enables this device for Agent.
Enable Enable<public>():void Enables this device.
Disable Disable<public>(Agent:agent):void Disables this device for Agent. While disabled this device will not receive signals.
Disable Disable<public>():void Disables this device. While disabled this device will not receive signals.
ResetForAll ResetForAll<public>(Agent:agent):void Resets the timer back to its base time and stops it for all agents.
ResetForAll ResetForAll<public>():void Resets the timer back to its base time and stops it for all agents.
Start Start<public>(Agent:agent):void Starts the timer for Agent.
Start Start<public>():void Starts the timer.
Pause Pause<public>(Agent:agent):void Pauses the timer for Agent.
Pause Pause<public>():void Pauses the timer.
Resume Resume<public>(Agent:agent):void Resumes the timer for Agent.
Resume Resume<public>():void Resumes the timer.
Complete Complete<public>(Agent:agent):void Completes the timer for Agent.
Complete Complete<public>():void Completes the timer.
StartForAll StartForAll<public>(Agent:agent):void Starts the timer for all agents.
StartForAll StartForAll<public>():void Starts the timer for all agents.
PauseForAll PauseForAll<public>(Agent:agent):void Pauses the timer for all agents.
PauseForAll PauseForAll<public>():void Pauses the timer for all agents.
ResumeForAll ResumeForAll<public>(Agent:agent):void Resumes the timer for all agents.
ResumeForAll ResumeForAll<public>():void Resumes the timer for all agents.
CompleteForAll CompleteForAll<public>(Agent:agent):void Completes the timer for all agents.
CompleteForAll CompleteForAll<public>():void Completes the timer for all agents.
Save Save<public>(Agent:agent):void Saves this device's data for Agent.
Load Load<public>(Agent:agent):void Loads this device's saved data for Agent.
ClearPersistenceData ClearPersistenceData<public>(Agent:agent):void Clears this device's saved data for Agent.
ClearPersistenceDataForAll ClearPersistenceDataForAll<public>(Agent:agent):void Clears this device's saved data for all agents.
ClearPersistenceDataForAll ClearPersistenceDataForAll<public>():void Clears this device's saved data for all agents.
SetActiveDuration SetActiveDuration<public>(Time:float, Agent:agent):void Sets the remaining time (in seconds) on the timer, if active, on Agent.
SetActiveDuration SetActiveDuration<public>(Time:float):void Sets the remaining time (in seconds) on the timer, if active. Use this function if the timer is set to use the same time for all agent's.
GetActiveDuration GetActiveDuration<public>(Agent:agent)<transacts>:float Returns the remaining time (in seconds) on the timer for Agent.
GetActiveDuration GetActiveDuration<public>()<transacts>:float Returns the remaining time (in seconds) on the timer if it is set to be global.
SetLapTime SetLapTime<public>(Agent:agent):void Sets the lap time indicator for Agent.
SetLapTimeForAll SetLapTimeForAll<public>(Agent:agent):void Sets the lap time indicator for all agents.
SetLapTimeForAll SetLapTimeForAll<public>():void Sets the lap time indicator for all agents.
SetMaxDuration SetMaxDuration<public>(Time:float):void Sets the maximum duration of the timer (in seconds).
GetMaxDuration GetMaxDuration<public>()<transacts>:float Returns the maximum duration of the timer (in seconds).
IsStatePerAgent IsStatePerAgent<public>()<transacts><decides>:void Succeeds if this device is tracking timer state for each individual agent independently. Fails if state is being tracked globally for all agent's.

Walkthrough

The scene: A sunny cel-shaded cove. A wooden pressure plate sits at the end of the dock. When a pirate steps on it, a treasure countdown begins — they have to reach the glowing chest on the clifftop before the timer runs out. We use two devices from /Fortnite.com/Devices: a trigger_device (the plate) and a timer_device (the countdown).

Notice the using block at the very top — those lines are the whole point of this article. /Fortnite.com/Devices gives us trigger_device and timer_device; /Verse.org/Simulation gives us creative_device and Subscribe.

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

# This whole file lives inside the modules imported above.
cove_treasure_run := class(creative_device):

    # @editable fields let you drag the placed devices in from the Outliner.
    @editable
    StartPlate : trigger_device = trigger_device{}

    @editable
    TreasureTimer : timer_device = timer_device{}

    OnBegin<override>()<suspends>:void =
        # Only let the run start once per life so pirates can't spam it.
        StartPlate.SetMaxTriggerCount(1)
        # A short cooldown before it can fire again if we ever reset.
        StartPlate.SetResetDelay(2.0)
        # Wire the plate's event to our handler method.
        StartPlate.TriggeredEvent.Subscribe(OnPlateStepped)
        # React to the timer finishing well or badly.
        TreasureTimer.SuccessEvent.Subscribe(OnTreasureReached)
        TreasureTimer.FailureEvent.Subscribe(OnTimeUp)
        # Enable both devices so they respond.
        StartPlate.Enable()
        TreasureTimer.Enable()

    # TriggeredEvent hands us (Agent : ?agent) — an OPTIONAL agent.
    OnPlateStepped(Agent : ?agent):void =
        if (Pirate := Agent?):
            # Start the countdown just for the pirate who stepped on the plate.
            TreasureTimer.Start(Pirate)

    OnTreasureReached(Agent : ?agent):void =
        if (Pirate := Agent?):
            # They made it! Give the plate back to the next player.
            StartPlate.Enable()

    OnTimeUp(Agent : ?agent):void =
        if (Pirate := Agent?):
            # Ran out of time — reset the timer for everyone.
            TreasureTimer.ResetForAll()

Line by line:

  • The two using lines are the module imports. Delete /Fortnite.com/Devices and trigger_device becomes an unknown identifier — the module is where that type is defined.
  • class(creative_device) — your script must be a creative_device to hold @editable device fields and run OnBegin.
  • SetMaxTriggerCount(1) and SetResetDelay(2.0) — real trigger_device methods configuring how often the plate fires.
  • TriggeredEvent.Subscribe(OnPlateStepped)Subscribe comes from the simulation module; it connects the device's event to a method.
  • OnPlateStepped(Agent : ?agent) — a listenable(?agent) always hands an optional agent. if (Pirate := Agent?) unwraps it safely.
  • TreasureTimer.Start(Pirate) — starts the countdown for just that pirate.
  • The timer's SuccessEvent / FailureEvent drive win/lose reactions.

Common patterns

Pattern 1 — Authoring your OWN module to share a helper

Here the file declares a module named cove_helpers and then usings it in the same file. The helper starts a timer for a pirate — logic you could reuse across many devices. This is exactly how you factor shared code out.

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

# Our own module — a named bundle of shared code we can import elsewhere.
cove_helpers := module:
    # A shared helper any device can call.
    BeginRunFor<public>(Timer : timer_device, Pirate : agent):void =
        Timer.Enable(Pirate)
        Timer.Start(Pirate)

# Import our module so its functions are in scope.
using { cove_helpers }

lagoon_starter := class(creative_device):

    @editable
    Plate : trigger_device = trigger_device{}

    @editable
    RunTimer : timer_device = timer_device{}

    OnBegin<override>()<suspends>:void =
        Plate.TriggeredEvent.Subscribe(OnStep)

    OnStep(Agent : ?agent):void =
        if (Pirate := Agent?):
            # Call the shared helper from our module.
            BeginRunFor(RunTimer, Pirate)

Pattern 2 — Timer control for everyone (module methods for all agents)

When a captain rings the ship's bell (a trigger), the whole crew's shared countdown starts. This uses the *ForAll overloads and shows a trigger with no reset limit.

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

ship_bell := class(creative_device):

    @editable
    Bell : trigger_device = trigger_device{}

    @editable
    CrewTimer : timer_device = timer_device{}

    OnBegin<override>()<suspends>:void =
        # 0 = no trigger limit; the bell can ring all match.
        Bell.SetMaxTriggerCount(0)
        Bell.TriggeredEvent.Subscribe(OnBellRung)
        CrewTimer.SuccessEvent.Subscribe(OnCrewFinished)

    OnBellRung(Agent : ?agent):void =
        # Start (and reset) the shared countdown for the entire crew.
        CrewTimer.ResetForAll()
        CrewTimer.StartForAll()

    OnCrewFinished(Agent : ?agent):void =
        # Pause the timer for everyone once the objective is met.
        CrewTimer.PauseForAll()

Pattern 3 — Reading timer state and adjusting duration

A lookout trigger checks how much time remains and, on a fresh start, sets a fixed active duration for that pirate. Shows GetActiveDuration/SetActiveDuration and a code-driven Trigger().

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

lookout_post := class(creative_device):

    @editable
    Lookout : trigger_device = trigger_device{}

    @editable
    DiveTimer : timer_device = timer_device{}

    OnBegin<override>()<suspends>:void =
        Lookout.TriggeredEvent.Subscribe(OnSpotted)
        DiveTimer.StartUrgencyModeEvent.Subscribe(OnUrgency)

    OnSpotted(Agent : ?agent):void =
        if (Pirate := Agent?):
            # Give this pirate a 30-second dive window, then start.
            DiveTimer.SetActiveDuration(30.0, Pirate)
            DiveTimer.Start(Pirate)

    OnUrgency(Agent : ?agent):void =
        # Time is almost up — fire the trigger from code (no agent needed).
        Lookout.Trigger()

Gotchas

  • 'Unknown identifier' almost always means a missing using. If timer_device or Subscribe aren't recognized, add using { /Fortnite.com/Devices } and using { /Verse.org/Simulation }. The module is where the name is defined.
  • using goes at the top, before definitions. Verse is explicit — it will not auto-import anything for you.
  • Optional agents must be unwrapped. TriggeredEvent, SuccessEvent, FailureEvent, and StartUrgencyModeEvent are all listenable(?agent). Always do if (Pirate := Agent?): before using the pirate.
  • @editable device fields are required to call a placed device. A bare Timer.Start() at file scope fails — the device must be a field inside your class(creative_device) and assigned in the Outliner.
  • Start() vs Start(Agent) vs StartForAll() are different overloads. Per-agent timers only affect one pirate; use the ForAll versions for the whole lobby.
  • Your own module's members need <public> to be usable outside it. In Pattern 1, BeginRunFor<public> is callable after using { cove_helpers }; drop <public> and it stays hidden.
  • No intfloat auto-convert. SetActiveDuration and SetResetDelay take float — write 30.0, not 30.
  • A message param needs localized text, e.g. MyText<localizes>(S:string):message = "{S}" — there is no StringToMessage. (None of these device methods take a message, but keep it in mind when you add HUD text.)

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 →