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
TriggeredEventand run Verse logic the moment a player (or your code) fires the trigger. - Fire programmatically — call
Trigger()orTrigger(Agent)from Verse to kick off linked devices without any player input. - Gate and throttle — use
SetMaxTriggerCount,SetResetDelay, andSetTransmitDelayto 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:
- Place a Trigger Device named
PressurePlate— set Triggered By Player = true, Visible In Game = false. - Place a second Trigger Device named
VaultRelay— set Triggered By Player = false (Verse drives it). - Link
VaultRelay's Triggered output to your barrier/door device's Open input in the device graph. - 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 : ?agent—TriggeredEventis alistenable(?agent). The payload is an optional agent because the trigger can fire from code (no player). Always treat it as?agentin 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.