Marooned Town: fire-and-forget with spawn
In this lesson you'll learn to
- βStudent can launch independent async tasks with spawn{} and knows when spawn is right vs. awaiting inline.
Student can launch independent async tasks with spawn{} and knows when spawn is right vs. awaiting inline.
π Reference & full walkthrough: Marooned Town: fire-and-forget with spawn
π§© Your capstone piece: One spawned per-racer monitor task (position/checkpoint watcher) per player at race start
What you'll learn
You'll learn how to launch a Verse function asynchronously with the spawn expression so background work never freezes gameplay. You'll combine Sleep for timed delays, GetRandomFloat for variable timing, and the player's HUD message device (hud_message_device) to deliver a delayed, non-blocking UI update to each player. The same pattern powers countdowns, live stats, and staggered notifications.
How it works
Verse runs your device logic cooperatively on a single thread. If you put a long Sleep loop directly inside an event handler, that handler holds the line until it finishes. The spawn expression breaks free of that: it starts a <suspends> function as an independent task that runs alongside everything else. Your TriggeredEvent handler returns immediately while the spawned task waits, then updates the UI later.
Three rules matter here:
- The spawned function MUST be marked
<suspends>because it callsSleep. spawn{ Foo() }(orspawn Foo()) is called with PARENS βFoois an ordinary<suspends>function, not a<decides>one.GetRandomFloatis<transacts>and returns a plainfloat, so call it with()and store the value β no brackets.
To make the result visible we drive a hud_message_device. Calling Show(Agent) displays its configured text on that player's HUD, which is our concrete "UI update."
Let's build it
Place a Trigger Device and a HUD Message Device (with some text configured) in your level, then assign both to the Verse device below. Stepping on the trigger spawns a background task that waits a random 1β3 seconds, then shows the HUD message to the player who triggered it.
using { /Fortnite.com/Devices }
using { /Fortnite.com/Devices/Patchwork }
using { /Verse.org/Simulation }
using { /Verse.org/Random }
using { /Verse.org/Verse }
using { /UnrealEngine.com/Temporary/Diagnostics }
# A device that spawns a background task to update the Player UI (HUD) after a delay.
spawn_ui_device := class<concrete>(creative_device):
# The trigger the player steps on to kick off the async task.
@editable TriggerDevice : trigger_device = trigger_device{}
# The HUD message shown to the player once the background task finishes.
@editable SuccessMessage : hud_message_device = hud_message_device{}
# Async task: wait a random amount of time, then update the player's HUD.
# Marked <suspends> because it calls Sleep.
UpdatePlayerUIAsync(TriggeringAgent : agent)<suspends> : void =
# GetRandomFloat is <transacts> and returns a float β call with (), store it.
Delay : float = GetRandomFloat(1.0, 3.0)
Print("Background task started, waiting {Delay} seconds...")
# Yield this task for the delay; the rest of the game keeps running.
Sleep(Delay)
# Update the UI: show the configured HUD message to the triggering player.
SuccessMessage.Show(TriggeringAgent)
Print("UI updated for the player after the delay.")
# Entry point.
OnBegin<override>()<suspends> : void =
# Subscribe to the trigger. The handler returns immediately because the
# slow work is launched with spawn instead of run inline.
TriggerDevice.TriggeredEvent.Subscribe(OnTriggered)
# Event handler: not <suspends>, so it must NOT call Sleep directly.
# spawn launches the async function as an independent task.
# The TriggeredEvent passes an ?agent, so accept that and bind it.
OnTriggered(MaybeAgent : ?agent) : void =
Print("Trigger fired β spawning background UI task.")
if (Agent := MaybeAgent?):
spawn{ UpdatePlayerUIAsync(Agent) }```
## Try it yourself
1. Place a **Trigger Device** and a **HUD Message Device** in your level.
2. On the HUD Message Device, set its **Message** text (e.g. "Success!").
3. Place a **Verse Device** running `spawn_ui_device`.
4. In its details panel, assign the Trigger to `TriggerDevice` and the HUD Message Device to `SuccessMessage`.
5. Play, step on the trigger, and keep moving. The game never freezes β the HUD message appears 1β3 seconds later thanks to the spawned task.
## Recap
You used `spawn` to run a `<suspends>` function as an independent background task, keeping your trigger handler instant and non-blocking. `Sleep` provided the timed delay, `GetRandomFloat` (called with parens, returning a `float`) varied the timing, and `hud_message_device.Show(Agent)` delivered the actual UI update. Reach for `spawn` when you need fire-and-forget async work; reach for `race`, `sync`, or `branch` when you need structured coordination.
Keep going β free
You've read the intro. The rest of this lesson is free for members. Sign in to continue and track your progress.
Sign in free to continue this lessonSources
/guides/sug-launching-asynchronous-logic-with-spawn-in-verseBiloxi Studios original lesson
Add this lesson to your free study plan.
π§ The Keeperβs log
Quest complete? Chart your next heading from the π¦ West Coves expedition.
β΅ Take me there