Reference Devices compiles

trigger_device: The Relay That Wires Your World Together

The `trigger_device` is UEFN's universal relay — it fires a `TriggeredEvent` that your Verse code can subscribe to, and it can be fired programmatically to chain reactions across your map. Whether you need a vault door that opens exactly three times, a cinematic that plays only after a player steps on a pressure plate, or a timed reset between activations, `trigger_device` and its base class `trigger_base_device` give you the knobs to control it all. Master this device and you master the backbon

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

Overview

The trigger_device is a concrete relay device placed in your UEFN level. It sits at the center of almost every event-driven system:

  • React to the world — subscribe to TriggeredEvent and run Verse logic the moment a player (or your code) fires the trigger.
  • Fire programmatically — call Trigger() or Trigger(Agent) from Verse to kick off linked devices without any player input.
  • Gate and throttle — use SetMaxTriggerCount, SetResetDelay, and SetTransmitDelay to control how many times and how fast the trigger can fire.
  • Enable / Disable on demand — call Enable() / Disable() to open or close the trigger's window of activation at runtime.

trigger_base_device is the abstract parent shared by trigger_device, perception_trigger_device, and attribute_evaluator_device. All the count/delay/enable methods live there; trigger_device adds TriggeredEvent and the two Trigger() overloads.

When to reach for it:

  • You need a Verse handler to run when something happens in the world (player walks into a zone, button is pressed, timer expires).
  • You want to fire a chain of linked devices from code at a precise moment.
  • You need to limit how many times an interaction can happen (e.g., a chest that opens only once per round).

API Reference

trigger_base_device

Base class for various specialized trigger devices. See also: * trigger_device * perception_trigger_device * attribute_evaluator_device

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

trigger_base_device<public> := class<abstract><epic_internal>(creative_device_base):

Methods (call these to make the device act):

Method Signature Description
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.

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.

Walkthrough

Scenario: The Vault Door — opens three times, then locks forever

A player steps onto a pressure-plate trigger. The vault door (represented by a second trigger that drives a linked barrier device) opens. After three uses the system disables itself. A 2-second reset delay prevents spam-clicking. A 0.5-second transmit delay gives the barrier animation time to start before downstream devices react.

UEFN setup:

  1. Place a Trigger Device named PressurePlate — set Triggered By Player = true, Visible In Game = false.
  2. Place a second Trigger Device named VaultRelay — set Triggered By Player = false (Verse drives it).
  3. Link VaultRelay's Triggered output to your barrier/door device's Open input in the device graph.
  4. Drag your Verse device onto the map and assign both triggers in the Details panel.
vault_door_controller := class(creative_device):

    # Pressure plate the player walks onto
    @editable
    PressurePlate : trigger_device = trigger_device{}

    # Relay that drives the linked barrier/door device
    @editable
    VaultRelay : trigger_device = trigger_device{}

    # How many times the vault may open
    MaxOpenCount : int = 3

    OnBegin<override>()<suspends> : void =
        # Allow exactly 3 activations on the relay
        VaultRelay.SetMaxTriggerCount(MaxOpenCount)

        # 2-second cooldown between openings
        VaultRelay.SetResetDelay(2.0)

        # 0.5-second delay before downstream devices are notified
        VaultRelay.SetTransmitDelay(0.5)

        # Pressure plate has unlimited triggers so it always listens
        PressurePlate.SetMaxTriggerCount(0)

        # Subscribe: when a player steps on the plate, open the vault
        PressurePlate.TriggeredEvent.Subscribe(OnPlateTriggered)

        # Subscribe: react every time the vault relay actually fires
        VaultRelay.TriggeredEvent.Subscribe(OnVaultOpened)

    # Called each time the pressure plate fires
    OnPlateTriggered(MaybeAgent : ?agent) : void =
        # Check how many vault openings remain before forwarding
        Remaining := VaultRelay.GetTriggerCountRemaining()
        if (Remaining = 0):
            # 0 means unlimited — should not happen here, but guard anyway
            VaultRelay.Trigger()
        else if (Remaining > 0):
            VaultRelay.Trigger()   # fire the relay (no agent needed)
        # When Remaining would go negative the device self-disables per MaxTriggerCount

    # Called each time the vault relay fires successfully
    OnVaultOpened(MaybeAgent : ?agent) : void =
        Remaining := VaultRelay.GetTriggerCountRemaining()
        if (Remaining = 1):
            # This was the last allowed opening — disable the plate too
            PressurePlate.Disable()

Line-by-line breakdown:

Lines What's happening
VaultRelay.SetMaxTriggerCount(3) Clamps the relay to fire at most 3 times total (clamped to [0,20]).
VaultRelay.SetResetDelay(2.0) After each fire, the relay ignores new triggers for 2 seconds.
VaultRelay.SetTransmitDelay(0.5) Linked devices (the barrier) are notified 0.5 s after the relay fires.
PressurePlate.SetMaxTriggerCount(0) 0 = unlimited; the plate always listens.
TriggeredEvent.Subscribe(...) Registers a class-scope method as the handler — no lambda needed.
VaultRelay.GetTriggerCountRemaining() Reads remaining uses before firing so we can react to the last one.
PressurePlate.Disable() Shuts the plate down after the vault is exhausted.

Note on MaybeAgent : ?agentTriggeredEvent is a listenable(?agent). The payload is an optional agent because the trigger can fire from code (no player). Always treat it as ?agent in your handler signature.

Common patterns

Pattern 1 — Unwrapping the agent from TriggeredEvent

When you need to know which player stepped on the trigger (e.g., to grant them a weapon or display their name), unwrap the optional agent safely.

agent_logger := class(creative_device):

    @editable
    ZoneTrigger : trigger_device = trigger_device{}

    OnBegin<override>()<suspends> : void =
        ZoneTrigger.TriggeredEvent.Subscribe(OnZoneEntered)

    OnZoneEntered(MaybeAgent : ?agent) : void =
        # Unwrap: only proceed when a real player caused the trigger
        if (A := MaybeAgent?):
            # A is now a concrete `agent` — safe to use with other APIs
            # e.g. grant items, update score, start a cinematic, etc.
            ZoneTrigger.Disable()   # one-shot: disable after first real player

Key point: if (A := MaybeAgent?) is the idiomatic Verse way to unwrap ?agent. If the trigger fired from code (no agent), MaybeAgent is false and the block is skipped.


Pattern 2 — Programmatic Trigger with an Agent reference

Sometimes your code is the one firing the trigger, but you still want downstream devices to know which player caused it (e.g., a leaderboard device that tracks per-player activations).

code_fired_trigger := class(creative_device):

    @editable
    RewardRelay : trigger_device = trigger_device{}

    @editable
    CheckpointTrigger : trigger_device = trigger_device{}

    OnBegin<override>()<suspends> : void =
        # No transmit delay — fire linked devices immediately
        RewardRelay.SetTransmitDelay(0.0)
        # Allow up to 5 reward grants total
        RewardRelay.SetMaxTriggerCount(5)

        CheckpointTrigger.TriggeredEvent.Subscribe(OnCheckpointReached)

    OnCheckpointReached(MaybeAgent : ?agent) : void =
        if (A := MaybeAgent?):
            # Pass the agent so linked score/leaderboard devices credit the right player
            RewardRelay.Trigger(A)
        else:
            # Fired without a player — use the no-agent overload
            RewardRelay.Trigger()

Key point: Trigger(Agent) and Trigger() are two separate overloads. Use the agent overload when downstream devices need player attribution.


Pattern 3 — Reading and adjusting delays at runtime

You can read back the current settings with the Get* methods and adjust them dynamically — useful for difficulty scaling or progressive challenges.

difficulty_scaler := class(creative_device):

    @editable
    HazardTrigger : trigger_device = trigger_device{}

    OnBegin<override>()<suspends> : void =
        # Start with a generous reset delay
        HazardTrigger.SetResetDelay(5.0)
        HazardTrigger.SetMaxTriggerCount(0)  # unlimited
        HazardTrigger.TriggeredEvent.Subscribe(OnHazardFired)

    OnHazardFired(MaybeAgent : ?agent) : void =
        # Each time the hazard fires, read the current delay and halve it
        CurrentDelay : float = HazardTrigger.GetResetDelay()
        NewDelay : float = CurrentDelay / 2.0
        # Clamp to a minimum of 0.5 seconds so it never becomes instant
        if (NewDelay >= 0.5):
            HazardTrigger.SetResetDelay(NewDelay)
        else:
            HazardTrigger.SetResetDelay(0.5)

        # Also check how many triggers remain (0 = unlimited)
        MaxCount : int = HazardTrigger.GetMaxTriggerCount()
        Remaining : int = HazardTrigger.GetTriggerCountRemaining()
        # (use MaxCount / Remaining for UI feedback, scoring, etc.)
        _ = MaxCount
        _ = Remaining

Key point: GetResetDelay() and GetMaxTriggerCount() are <transacts> — they can be called anywhere, including inside event handlers. GetTriggerCountRemaining() returns 0 when the limit is unlimited (MaxCount = 0), not when it's exhausted.

Gotchas

1. TriggeredEvent hands you ?agent, not agent

The event signature is listenable(?agent). Your handler must be (MaybeAgent : ?agent) : void. If you write (A : agent) the code will not compile. Always unwrap with if (A := MaybeAgent?): before using the agent.

2. GetTriggerCountRemaining() returns 0 for unlimited, not exhausted

When SetMaxTriggerCount(0) (unlimited), GetTriggerCountRemaining() returns 0 — the same value it returns when the device is exhausted. Use GetMaxTriggerCount() first to distinguish: if GetMaxTriggerCount() = 0 the trigger is unlimited; otherwise GetTriggerCountRemaining() is the real remaining count.

3. SetMaxTriggerCount is clamped to [0, 20]

Passing a value above 20 silently clamps to 20. If your design needs more than 20 firings, set the count to 0 (unlimited) and manage your own counter in Verse.

4. @editable is mandatory — bare identifiers fail

You cannot write trigger_device.Trigger() at the top level. Every device reference must be an @editable field inside a class(creative_device). The UEFN editor wires the placed device to the field at runtime.

5. SetResetDelay vs SetTransmitDelay — they are different clocks

  • ResetDelay — how long before the trigger itself can fire again.
  • TransmitDelay — how long before linked downstream devices are notified after a fire. Both run after a trigger fires, but they control different things. Setting only one does not affect the other.

6. Enable / Disable survive SetMaxTriggerCount

Disabling a trigger prevents it from receiving any activation, regardless of remaining count. Re-enabling it does not reset the count — use the count APIs separately if you also want to restore uses.

7. No using directives needed in your Verse device file

The UEFN compile gate injects the required using blocks automatically. Do not add using { /Fortnite.com/Devices/Patchwork } or similar lines manually — they can cause duplicate-import errors in some SDK versions.

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