Overview
OnBegin is the method the Fortnite runtime calls on your creative_device the moment the game experience begins (at the start of each round). It is not a device you drag in from the content browser — it's the override that lives inside your own Verse-authored creative_device. Think of it as main() for a UEFN device: the single place where your code first gets to run.
The game problem it solves: placed devices (a trigger, a vault door, a weapon granter) sit in your level doing nothing until some Verse code wires them together. OnBegin is where that wiring happens — you resolve your @editable references, subscribe to their events, and call their methods so a plate can unlock a door or a button can grant a weapon.
Reach for OnBegin literally every time you write a Verse device. Two signatures matter:
creative_device.OnBegin()<suspends>:void— runs when the round starts. This is the one you override 99% of the time.npc_behavior.OnBegin()<suspends>:void— the parallel entry point for a custom NPC behavior, called when the NPC is added to the simulation.
The <suspends> effect is the key superpower: OnBegin is a coroutine, so you can Sleep, run async MoveTo animations, and race/sync long-running tasks right from the entry point.
API Reference
(API surface could not be resolved for this device.)
Walkthrough
Let's build a real scenario: a vault room. When a player steps on a pressure plate, we flash a warning VFX, wait one second, then slide the vault door (a Verse-controlled creative_device) upward to open it. This uses the creative_device entry point plus MoveTo and the VFX spawner's Enable.
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/SpatialMath }
# A Verse-authored device that acts as the vault door itself.
vault_room_device := class(creative_device):
# The pressure plate the player steps on.
@editable
PressurePlate : trigger_device = trigger_device{}
# A VFX spawner that flashes a warning before the door opens.
@editable
WarningVfx : vfx_spawner_device = vfx_spawner_device{}
# How high (in cm) the vault door slides up when opening.
@editable
OpenHeight : float = 300.0
# Called by the runtime when the round begins — our entry point.
OnBegin<override>()<suspends>:void =
# Wire the plate's TriggeredEvent to our handler.
PressurePlate.TriggeredEvent.Subscribe(OnPlateStepped)
# Event handler: a listenable(?agent) hands us (Agent : ?agent).
OnPlateStepped(Agent : ?agent):void =
# Kick off the async open sequence. spawn lets us call a
# <suspends> function from a non-suspends handler.
spawn { OpenVault() }
# The open sequence runs as a coroutine.
OpenVault()<suspends>:void =
# Flash the warning effect.
WarningVfx.Enable()
Sleep(1.0)
WarningVfx.Disable()
# Compute the target transform: same rotation, raised position.
StartTransform := GetTransform()
TargetPosition := StartTransform.Translation + vector3{Z := OpenHeight}
# Slide the door up over 2 seconds.
MoveTo(TargetPosition, StartTransform.Rotation, 2.0)
Line by line:
vault_room_device := class(creative_device)— we inherit fromcreative_device, so this class shows up in the content browser and can be placed in the level.- The three
@editablefields let a designer pick which plate, which VFX spawner, and how far the door moves — all set in the Details panel in UEFN. OnBegin<override>()<suspends>:void =— the entry point.<override>says we're replacing the base method;<suspends>marks it a coroutine.PressurePlate.TriggeredEvent.Subscribe(OnPlateStepped)— you MUST subscribe insideOnBegin; a bare device call outside a placed reference fails with 'Unknown identifier'.OnPlateStepped(Agent : ?agent)— trigger events arelistenable(?agent), so the handler receives an optional agent.spawn { OpenVault() }— the handler is not<suspends>, so wespawnthe coroutine to run the timed sequence concurrently.WarningVfx.Enable()/Disable()— real methods onvfx_spawner_device.MoveTo(TargetPosition, StartTransform.Rotation, 2.0)— thecreative_deviceslides itself to the new spot over 2 seconds.
Common patterns
Pattern 1 — Reset per-round state in OnBegin. Because OnBegin fires at the start of every round, it's the natural spot to reset progress. Here we drive a progress_based_mesh_device back to zero each round.
using { /Fortnite.com/Devices }
round_reset_device := class(creative_device):
@editable
ProgressMesh : progress_based_mesh_device = progress_based_mesh_device{}
OnBegin<override>()<suspends>:void =
# Fresh round: wipe progress back to the start.
set ProgressMesh.CurrentProgress = 0.0
set ProgressMesh.ProgressTarget = 100.0
Pattern 2 — Restart a burst VFX from OnBegin. The VFX spawner's Restart re-triggers a burst effect; calling it in the entry point gives an opening flourish when the round starts.
using { /Fortnite.com/Devices }
intro_burst_device := class(creative_device):
@editable
OpeningVfx : vfx_spawner_device = vfx_spawner_device{}
OnBegin<override>()<suspends>:void =
OpeningVfx.Enable()
# Fire the burst effect right as the game begins.
OpeningVfx.Restart()
Pattern 3 — The NPC entry point. npc_behavior has its own OnBegin, called when the NPC joins the simulation. Grab the agent there to start your AI logic.
using { /Fortnite.com/AI }
using { /Fortnite.com/Characters }
using { /Verse.org/Simulation }
guard_behavior := class(npc_behavior):
# Entry point for a custom NPC behavior.
OnBegin<override>()<suspends>:void =
# Resolve the agent this behavior is driving.
if (Agent := GetAgent[]):
# Now we can drive this specific NPC.
Sleep(1.0)
Gotchas
- You can only call placed devices through
@editablefields. A bareSomeTrigger.Method()with no declared field fails to compile with 'Unknown identifier'. Declare the field, assign it in the UEFN Details panel, then use it. - Subscribe inside
OnBegin, not at class scope. Event subscriptions are statements — they must run somewhere.OnBeginis where you run them. OnBeginis<suspends>, but event handlers usually aren't. To call a<suspends>helper (like an asyncMoveTosequence) from a plain handler, wrap it inspawn { ... }.- Unwrap the optional agent. A
listenable(?agent)handler receives(Agent : ?agent). You cannot use it directly — doif (A := Agent?):first. - No int↔float auto-conversion.
OpenHeightandCurrentProgressarefloat; feed them float literals like300.0, and useRound[Value](which<decides>, so it needs[]and a failure context) if you ever need an int. OnEndis not a coroutine and may not finish. The docs warn that coroutines spawned insideOnEndmay never execute — do teardown work synchronously there, not withSleep.- Don't confuse the two OnBegins.
creative_device.OnBeginruns at round start;npc_behavior.OnBeginruns when that NPC spawns into the simulation. They're separate overrides on separate base classes.