
Master Verse Rush for Concurrent Game Logic
What you'll learn
In Verse, time flow is a first-class language feature. Normally code runs top-to-bottom, one expression after another. But games are inherently concurrent: enemies spawn, HUDs animate, and timers tick all at the same moment. The rush expression groups two or more async expressions (functions marked <suspends>, Sleep, event awaits) so they start together.
The key behavior that sets rush apart from race: when the fastest subexpression completes, the expression that follows rush is evaluated — but the slower subexpressions are not canceled. They keep running to completion. That makes rush ideal for kicking off independent background work while reacting immediately to the first result.
How it works
Think of rush like a director shouting "Action!" at several actors simultaneously. All subexpressions begin at once. As soon as one finishes, your code moves on, but the others continue in the background.
A few rules that keep rush correct:
rushmay only appear in a<suspends>context (likeOnBegin), because its subexpressions are async.- Every subexpression must itself be async — calling
Sleep, awaiting an event, or invoking a<suspends>helper. - To actually accomplish something visible, our subtasks call real player-UI APIs. We reach the HUD with
Player.GetPlayerUI[](a<decides>call, so it goes in anif) and push widgets withPlayerUI.AddWidget(Widget).
We build a text_block widget, show it immediately in one subtask, then in a second subtask wait two seconds and swap the displayed text. Because both subtasks live inside rush, the immediate update and the delayed update are scheduled concurrently and neither blocks the other.
Let's build it
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/UI }
using { /UnrealEngine.com/Temporary/Diagnostics }
using { /Fortnite.com/Devices }
using { /Verse.org }
using { /Fortnite.com/UI }
# A device that shows a HUD message, then concurrently updates it after a delay using `rush`.
rush_ui_device := class<concrete>(creative_device):
# Async helper: show initial text on the player's HUD immediately.
# It is <suspends> so it can be a rush subexpression; Sleep(0.0) yields once.
ShowOnline(TextWidget:text_block)<suspends>:void =
Print("Task 1: pushing 'System Online' to HUD")
TextWidget.SetText(StringToMessage("System Online"))
Sleep(0.0) # yield to other concurrent tasks this frame
Print("Task 1: HUD update sent")
# Async helper: wait, then swap the HUD text. Runs concurrently with ShowOnline.
ShowComplete(TextWidget:text_block)<suspends>:void =
Print("Task 2: waiting 2 seconds...")
Sleep(2.0)
TextWidget.SetText(StringToMessage("Task Complete"))
Print("Task 2: delayed HUD update sent")
# Convert a plain string into a message for the text_block.
StringToMessage<localizes>(Value:string):message = "{Value}"
OnBegin<override>()<suspends>:void =
# Reach the first player; GetPlayers() returns an array, array{0} is fallible.
if (Player := GetPlayspace().GetPlayers()[0]):
# GetPlayerUI is <decides> — call it inside the if and bind the result.
if (PlayerUI := GetPlayerUI[Player]):
# Build a real text widget and add it to the HUD before rushing.
Label := text_block{DefaultText := StringToMessage("Booting...")}
PlayerUI.AddWidget(Label)
# rush: both subtasks start together. When the fastest (ShowOnline)
# completes, execution continues past rush; ShowComplete keeps running.
rush:
ShowOnline(Label)
ShowComplete(Label)
Print("rush returned (fastest task done); slower task still finishing.")
Try it yourself
- Add a third subtask to the
rushblock (for example, one thatSleep(1.0)then prints) and observe that the line afterrushfires as soon as the fastest one finishes, while the others continue. - Swap
rushforraceand watch the difference:racecancels the slower tasks, so the 2-second update never appears. - Replace
Sleep(0.0)inShowOnlinewithSleep(3.0)so it becomes the slowest. Notice the post-rushline now fires whenShowCompletefinishes instead. - Capture a
rushresult by assigning it:Result := rush: ...and feed the winner into your next expression.
Recap
rushruns two or more async expressions concurrently and continues as soon as the fastest completes — without canceling the slower ones (unlikerace).- It must live in a
<suspends>context, and every subexpression must be async. - We performed the technique for real:
GetPlayerUI[Player](a<decides>call insideif) plusAddWidgetandtext_block.SetTextto drive a live HUD from concurrent tasks. - Use
rushfor independent background work where one immediate result shouldn't wait on slower side effects.
Check your understanding
Test yourself with an interactive quiz and track your progress + earn XP — free for members.
Turn this into a guided course
Add Implementing Concurrent Logic with Rush Expressions in Verse to your free study plan — we'll suggest related pages and stitch the lot into one compile-checked, self-guided lesson with worked examples and quizzes.
Original tutorial generated by Verse Island from the Verse/UEFN knowledge base, with references to the Epic Games sources above. Code is validated against the knowledge base.