Reference Verse compiles

timer_device: Race the Clock on the Sunny Dock

The `timer_device` is your island's official timekeeper — a countdown or stopwatch that fires events when time runs out or a goal is met. Drop it into a cove speedrun, a clifftop survival challenge, or a dock-side fetch quest and it handles all the clock logic so your Verse code can focus on the fun. This article walks you through every major method and event with a complete, sunny-dock scenario you can drop straight into your island.

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

Overview

The timer_device tracks how long something takes, either counting down toward a deadline (countdown mode) or counting up as a stopwatch. When the clock hits zero the device fires SuccessEvent or FailureEvent depending on how it was configured, and a separate StartUrgencyModeEvent fires when the remaining time drops into the "urgency" threshold you set in the device properties panel.

Reach for timer_device when you need:

  • A timed challenge (swim from the dock to the buoy before the wave hits)
  • A survival window (hold the clifftop for 60 seconds)
  • A per-player clock that can be paused mid-round and resumed later
  • Persistent best-times saved between sessions via Save / Load

Because the device manages its own UI widget and urgency flash, you get a polished countdown HUD for free — no custom UI code required for the basic case.

API Reference

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

Scenario — Dock Sprint: Beat the Tide

The player steps onto a pressure plate at the end of the sunny dock. A 30-second countdown starts. If they reach the buoy trigger before time runs out the timer is completed (success). If the clock hits zero first, failure fires and they're sent back. While the timer is running, stepping off the dock into the water pauses the clock (you're swimming, not sprinting); stepping back on resumes it.

Devices needed in your UEFN scene:

  • 1 × timer_device — the countdown clock (set Max Duration = 30 s in properties)
  • 1 × button_device (the dock start plate — we model it as a trigger for simplicity)
  • 1 × trigger_device (the buoy finish zone)
  • 1 × trigger_device (the water zone — pause trigger)
  • 1 × trigger_device (return-to-dock zone — resume trigger)
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }

# dock_sprint_manager — attach to a Verse Device actor in your scene.
dock_sprint_manager := class(creative_device):

    # Wire these up in the UEFN Details panel.
    @editable
    DockTimer : timer_device = timer_device{}

    @editable
    StartPlate : trigger_device = trigger_device{}

    @editable
    BuoyFinish : trigger_device = trigger_device{}

    @editable
    WaterZone : trigger_device = trigger_device{}

    @editable
    ReturnZone : trigger_device = trigger_device{}

    # Called once when the island session begins.
    OnBegin<override>()<suspends> : void =
        # Subscribe to the dock start plate — a player stepping on it starts the clock.
        StartPlate.TriggeredEvent.Subscribe(OnDockStart)

        # Subscribe to the buoy finish zone — reaching it completes the timer (success).
        BuoyFinish.TriggeredEvent.Subscribe(OnBuoyReached)

        # Pause the clock when the player splashes into the water zone.
        WaterZone.TriggeredEvent.Subscribe(OnEnterWater)

        # Resume when they climb back onto the dock.
        ReturnZone.TriggeredEvent.Subscribe(OnReturnToDock)

        # React to the timer's own success/failure events.
        DockTimer.SuccessEvent.Subscribe(OnTimerSuccess)
        DockTimer.FailureEvent.Subscribe(OnTimerFailure)

        # React when urgency mode kicks in (e.g. last 10 seconds).
        DockTimer.StartUrgencyModeEvent.Subscribe(OnUrgency)

    # --- Event handlers ---

    # Player stepped on the dock start plate — start the countdown for that player.
    OnDockStart(MaybeAgent : ?agent) : void =
        if (Agent := MaybeAgent?):
            DockTimer.Start(Agent)

    # Player reached the buoy — mark the timer complete (triggers SuccessEvent).
    OnBuoyReached(MaybeAgent : ?agent) : void =
        if (Agent := MaybeAgent?):
            DockTimer.Complete(Agent)

    # Player fell into the water — pause their personal clock.
    OnEnterWater(MaybeAgent : ?agent) : void =
        if (Agent := MaybeAgent?):
            DockTimer.Pause(Agent)

    # Player climbed back onto the dock — resume their clock.
    OnReturnToDock(MaybeAgent : ?agent) : void =
        if (Agent := MaybeAgent?):
            DockTimer.Resume(Agent)

    # SuccessEvent sends ?agent — unwrap before use.
    OnTimerSuccess(MaybeAgent : ?agent) : void =
        if (A := MaybeAgent?):
            # Save the winning time so it persists across sessions.
            DockTimer.Save(A)

    # FailureEvent sends ?agent — unwrap before use.
    OnTimerFailure(MaybeAgent : ?agent) : void =
        if (A := MaybeAgent?):
            # Reset the clock so they can try again immediately.
            DockTimer.ResetForAll(A)

    # StartUrgencyModeEvent — clock is in the red zone.
    OnUrgency(MaybeAgent : ?agent) : void =
        # You could trigger a visual effect device here.
        # The timer's built-in urgency flash already fires automatically.
        if (A := MaybeAgent?):
            DockTimer.Resume(A)  # ensure it's still ticking (no-op if already running)```

### Line-by-line explanation

| Lines | What's happening |
|---|---|
| `@editable` fields | Every device reference must be declared as an editable field on the class — you cannot reference a placed device any other way. Wire them in the UEFN Details panel. |
| `OnBegin<override>()<suspends>` | The island entry point. All subscriptions happen here before any player arrives. |
| `StartPlate.TriggeredEvent.Subscribe(OnDockStart)` | `trigger_device.TriggeredEvent` sends a plain `agent` (not `?agent`), so the handler signature is `(Agent : agent)`. |
| `DockTimer.Start(Agent)` | Starts the countdown **for that specific player only** — other players' clocks are unaffected. |
| `DockTimer.Complete(Agent)` | Immediately ends the timer in success state, firing `SuccessEvent`. |
| `DockTimer.Pause(Agent)` / `Resume(Agent)` | Freezes and unfreezes the per-player clock without resetting it. |
| `OnTimerSuccess(MaybeAgent : ?agent)` | `SuccessEvent` is a `listenable(?agent)`  the payload is optional. Always unwrap with `if (A := MaybeAgent?):`. |
| `DockTimer.Save(A)` | Persists the current timer state for that agent so their best time survives a session restart. |
| `DockTimer.ResetForAll(A)` | Resets **all** players' clocks back to the configured max duration and stops them. |

---

## Common patterns

### Pattern 1 — Global countdown: everyone races together

A cove treasure hunt where every player on the island shares one visible clock. When time runs out for the group, the whole island fails.

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

cove_treasure_hunt := class(creative_device):

    @editable
    HuntTimer : timer_device = timer_device{}

    @editable
    TreasureChest : trigger_device = trigger_device{}

    OnBegin<override>()<suspends> : void =
        # Start the clock for EVERY player simultaneously.
        HuntTimer.StartForAll()

        TreasureChest.TriggeredEvent.Subscribe(OnChestOpened)
        HuntTimer.FailureEvent.Subscribe(OnHuntFailed)

    OnChestOpened(Agent : agent) : void =
        # One player found the treasure — complete for everyone (all win).
        HuntTimer.CompleteForAll()

    OnHuntFailed(MaybeAgent : ?agent) : void =
        # Time ran out — reset the whole island's timer so the round can restart.
        HuntTimer.ResetForAll()

Key calls: StartForAll(), CompleteForAll(), ResetForAll() — the no-argument overloads operate on every player at once.


Pattern 2 — Dynamic duration: adjust the clock mid-round

A clifftop survival mode where surviving players get bonus seconds added to their personal clock each time they eliminate an opponent.

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

clifftop_survival := class(creative_device):

    @editable
    SurvivalTimer : timer_device = timer_device{}

    @editable
    EliminationTrigger : trigger_device = trigger_device{}

    # Bonus seconds awarded per elimination.
    BonusSeconds : float = 10.0

    OnBegin<override>()<suspends> : void =
        SurvivalTimer.StartForAll()
        EliminationTrigger.TriggeredEvent.Subscribe(OnElimination)

    OnElimination(Agent : agent) : void =
        # Read how much time is left, then add the bonus.
        CurrentDuration : float = SurvivalTimer.GetActiveDuration(Agent)
        SurvivalTimer.SetActiveDuration(CurrentDuration + BonusSeconds, Agent)

Key calls: GetActiveDuration(Agent) reads the remaining seconds; SetActiveDuration(Time, Agent) writes a new remaining time — both are per-player.


Pattern 3 — Persistence: load a saved best time on session start

A shore-side time trial that remembers each player's personal best across sessions.

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

shore_time_trial := class(creative_device):

    @editable
    TrialTimer : timer_device = timer_device{}

    @editable
    StartGate : trigger_device = trigger_device{}

    @editable
    FinishGate : trigger_device = trigger_device{}

    OnBegin<override>()<suspends> : void =
        StartGate.TriggeredEvent.Subscribe(OnRaceStart)
        FinishGate.TriggeredEvent.Subscribe(OnRaceFinish)
        TrialTimer.SuccessEvent.Subscribe(OnNewBestTime)

    OnRaceStart(Agent : agent) : void =
        # Load any previously saved state for this player, then start.
        TrialTimer.Load(Agent)
        TrialTimer.Start(Agent)

    OnRaceFinish(Agent : agent) : void =
        TrialTimer.Complete(Agent)

    OnNewBestTime(MaybeAgent : ?agent) : void =
        if (A := MaybeAgent?):
            # Persist the finishing time for next session.
            TrialTimer.Save(A)

Key calls: Load(Agent) restores persisted state before starting; Save(Agent) commits the result after success.


Gotchas

1. SuccessEvent and FailureEvent send ?agent, not agent

SuccessEvent and FailureEvent are listenable(?agent). Your handler must accept (?agent) and unwrap it:

# CORRECT
OnSuccess(MaybeAgent : ?agent) : void =
    if (A := MaybeAgent?):
        DockTimer.Save(A)

# WRONG — compile error: type mismatch
OnSuccess(Agent : agent) : void = ...

StartUrgencyModeEvent is also listenable(?agent) — same rule applies.

2. trigger_device.TriggeredEvent sends plain agent, not ?agent

The trigger's event is listenable(agent) (non-optional), so its handler takes (Agent : agent) directly — no unwrap needed. Don't mix these up.

3. Per-agent vs. global overloads

Methods like Start, Pause, Resume, Complete, and ResetForAll each have two overloads: one that takes an Agent (per-player) and one with no argument (global). The global ResetForAll() resets all players even when called with an agent argument — read the signature carefully. StartForAll() / PauseForAll() / ResumeForAll() / CompleteForAll() are the explicit all-player variants.

4. SetActiveDuration only works while the timer is active

Calling SetActiveDuration on a timer that hasn't been started yet has no effect. Always call Start(Agent) first, then adjust the duration.

5. intfloat is never automatic

GetActiveDuration returns a float. If you do arithmetic with an integer literal, write it as a float literal (10.0, not 10) or you'll get a type-mismatch compile error.

6. Devices must be @editable fields

You cannot write timer_device{}.Start() inline — a bare constructor gives you a disconnected object with no island presence. Every device reference must be an @editable field wired in the UEFN Details panel.

7. ResetForAll(Agent) still resets everyone

Despite accepting an Agent parameter, ResetForAll(Agent) resets the timer for all agents, not just the one passed in. If you want a single-player reset, use Start(Agent) to restart just that player's clock.

Guides & scripts that use timer_device

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

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