Overview
The trigger_device is a relay. Its whole job is to detect that something happened and then broadcast that fact so other things can react. The "something" is usually a player walking into its volume, but you can also fire it from Verse code with Trigger().
Reach for it whenever you want a player action to cause a consequence:
- Step on a pressure plate → open a vault door.
- Walk through a doorway → start a cinematic.
- Enter an arena → teleport every player into the action.
The device exposes one event you subscribe to — TriggeredEvent — and a handful of methods to drive it from code (Trigger), turn it on and off (Enable/Disable), and tune its behaviour (SetMaxTriggerCount, SetResetDelay, SetTransmitDelay). Because TriggeredEvent hands you the agent who triggered it, you can run player-specific logic — give that player a reward, teleport that character, and so on.
The key Verse rule to remember: you can't call methods on a placed device unless you declare it as an @editable field inside a class(creative_device), then point that field at the placed device in the UEFN Details panel.
API Reference
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
Let's build a classic: a pressure plate that opens a vault door. We place a trigger_device on the floor where the player steps, and a second trigger_device wired (via Direct Event Binding in UEFN, or in code) to the door — but to keep everything in Verse and self-contained, we'll just react to the step directly and give the triggering player a celebratory message, then disable the plate so it only works once.
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/Diagnostics }
using { /Fortnite.com/Characters }
# Localized message helper — `message` params need a localizes value, not a raw string.
MyText<localizes>(S : string) : message = "{S}"
vault_room := class(creative_device):
# The pressure plate the player steps on. Point this at the placed trigger in UEFN.
@editable
PressurePlate : trigger_device = trigger_device{}
# A HUD message device to confirm the unlock (optional flavour).
@editable
UnlockMessage : hud_message_device = hud_message_device{}
OnBegin<override>()<suspends> : void =
# Only allow the plate to fire once, then stop reacting.
PressurePlate.SetMaxTriggerCount(1)
# Wait 0.5s after a trigger before the device tells other devices.
PressurePlate.SetTransmitDelay(0.5)
# Subscribe our handler to the event the plate fires when stepped on.
PressurePlate.TriggeredEvent.Subscribe(OnPlateStepped)
# TriggeredEvent hands us an OPTIONAL agent (?agent), because the device
# can also be triggered from code with no agent attached.
OnPlateStepped(MaybeAgent : ?agent) : void =
if (Agent := MaybeAgent?):
# We have a real player — confirm the vault is open just for them.
UnlockMessage.Show(Agent)
# Optional: react to their character (e.g. log position, etc.)
if (Char := Agent.GetFortCharacter[]):
Print("Player opened the vault!")
# Whether or not there was an agent, lock the plate down so it won't refire.
PressurePlate.Disable()
Line by line:
MyText<localizes>(...)— a helper so we could pass amessage; many message-taking APIs need localized text, never a rawstring.@editable PressurePlate : trigger_device = trigger_device{}— declares the field. After compiling, you select your placed plate in the device's Details panel. Without this field you cannot call any method on the plate.OnBegin<override>()<suspends>:void =— runs when the device starts in a live game.SetMaxTriggerCount(1)— clamps the plate so it fires at most once.SetTransmitDelay(0.5)— delays the outgoing signal by half a second (useful if you later wire it to a door via the device's bindings).TriggeredEvent.Subscribe(OnPlateStepped)— registers our method as the reaction. Subscriptions happen inOnBegin.OnPlateStepped(MaybeAgent : ?agent)— the handler. The parameter is?agent(optional!) because code-driven triggers send no agent.if (Agent := MaybeAgent?):— unwraps the option; the body only runs when a real player triggered it.UnlockMessage.Show(Agent)andAgent.GetFortCharacter[]— player-specific reactions.PressurePlate.Disable()— turns the device off so it stops reacting.
Common patterns
Fire a trigger from code to start a cinematic
You don't always wait for a player — sometimes your logic decides the moment. Here a different trigger is fired manually with Trigger(), which makes its own TriggeredEvent fire (with no agent). Wire that trigger to a cinematic in UEFN, and this code becomes your "play the cutscene now" button.
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
cinematic_starter := class(creative_device):
# Plate the player walks through to enter the cutscene zone.
@editable
EntryPlate : trigger_device = trigger_device{}
# This trigger is wired to a cinematic_sequence_device in UEFN bindings.
@editable
CinematicTrigger : trigger_device = trigger_device{}
OnBegin<override>()<suspends> : void =
EntryPlate.TriggeredEvent.Subscribe(OnEntered)
OnEntered(MaybeAgent : ?agent) : void =
if (Agent := MaybeAgent?):
# Pass the agent along so the cinematic trigger knows who started it.
CinematicTrigger.Trigger(Agent)
else:
# No agent (code path) — fire the agentless overload.
CinematicTrigger.Trigger()
Reusable plate with a cooldown and a budget
Use SetResetDelay for a cooldown between activations and SetMaxTriggerCount for a total budget. You can read the remaining budget with GetTriggerCountRemaining to react when the supply runs out.
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/Diagnostics }
loot_dispenser := class(creative_device):
@editable
LootPlate : trigger_device = trigger_device{}
OnBegin<override>()<suspends> : void =
# Can be used 5 times total, with a 3-second cooldown between uses.
LootPlate.SetMaxTriggerCount(5)
LootPlate.SetResetDelay(3.0)
LootPlate.TriggeredEvent.Subscribe(OnLootGrabbed)
OnLootGrabbed(MaybeAgent : ?agent) : void =
Remaining := LootPlate.GetTriggerCountRemaining()
Print("Loot grabbed. Charges left: {Remaining}")
if (Remaining = 0):
# Budget exhausted — shut the dispenser down.
LootPlate.Disable()
Read configured delays back out
The getters let your logic stay in sync with whatever you set in the Details panel or in code. Here we mirror the plate's reset delay into a Sleep so a follow-up effect lines up perfectly.
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/Diagnostics }
synced_plate := class(creative_device):
@editable
Plate : trigger_device = trigger_device{}
OnBegin<override>()<suspends> : void =
Plate.SetResetDelay(2.0)
Plate.TriggeredEvent.Subscribe(OnStepped)
OnStepped(MaybeAgent : ?agent) : void =
spawn{ WaitForReset() }
WaitForReset()<suspends> : void =
Delay := Plate.GetResetDelay()
Sleep(Delay)
Print("Plate is ready again after {Delay} seconds.")
Gotchas
TriggeredEventsends?agent, notagent. The device can be fired from code with no player, so the payload is optional. Always unwrap withif (Agent := MaybeAgent?):before using it. Trying to callAgent.GetFortCharacter[]on the raw?agentwon't compile.- You must have the
@editablefield, AND bind it in UEFN. A baretrigger_device{}field that you never point at a placed device will silently do nothing —Enable,Trigger, etc. operate on an unset device. SetMaxTriggerCountis clamped to [0,20]. Passing0means unlimited, not zero — andGetTriggerCountRemaining()returns0when the max is unlimited, so don't treat a0remaining as "empty" if you set the max to0.Trigger()vsTrigger(Agent). The agentless overload makesTriggeredEventfire withfalse/no agent; subscribers'?agentwill be empty. UseTrigger(Agent)when downstream logic needs to know who.- Subscribe in
OnBegin, not in a constructor. Event subscriptions must happen at runtime. Calling.Subscribeoutside the running device's lifecycle won't hook anything up. messageparams need localized text. If you call a method that takes amessage, use a<localizes>helper likeMyText("..."). There is noStringToMessage.- Verse never auto-converts int↔float.
SetResetDelaytakes afloat(2.0),SetMaxTriggerCounttakes anint(5). Mixing them up is a compile error.