Parallel Verse: Mastering sync for Concurrent Tasks
What you'll learn
You'll learn how to use the sync expression to run two or more async operations concurrently instead of one after another. We'll spin up three tasks that each Sleep for a different duration. Because they all start at the same moment, the total wait is the slowest task — not the sum of all of them.
How it works
Normally Verse code runs sequentially: each line finishes before the next begins. But Sleep is an async expression — it can take time across simulation updates. When you place several async expressions inside a sync: block, Verse starts them all at essentially the same moment and then waits for every subexpression to complete before continuing.
Key facts about sync:
- It must run in a
<suspends>context (likeOnBegin), because it awaits async work. - It acts as a barrier: nothing after the block runs until all tasks finish.
- It returns a tuple of each subexpression's result, in source order — access them with
Results(0),Results(1), etc.
So three sleeps of 1.0, 0.5, and 0.2 seconds finish in about 1.0 second total, because they overlap.
Let's build it
This device launches three async helper functions via sync. Each one prints a message after sleeping, and we read the tuple of results afterward to prove all three completed.
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /Verse.org/Verse }
using { /UnrealEngine.com/Temporary/Diagnostics }
# Demonstrates running several async tasks concurrently with `sync`.
parallel_sync_demo := class<concrete>(creative_device):
# An async helper: waits `Seconds`, logs, then returns a label string.
RunTask(Name:string, Seconds:float)<suspends>:string =
Print("{Name} started")
Sleep(Seconds) # async pause — this is what overlaps under sync
Print("{Name} finished after {Seconds}s")
# Stated value is the result returned to the sync tuple.
"{Name} done"
OnBegin<override>()<suspends>:void =
Print("Launching three tasks in parallel...")
# All three start at the same moment; sync waits for ALL of them.
# Total elapsed time is ~1.0s (the slowest), not 1.7s (the sum).
Results := sync:
RunTask("Task1", 1.0) # slowest -> determines total time
RunTask("Task2", 0.5)
RunTask("Task3", 0.2) # fastest
# This line only runs AFTER every task above has completed.
# `Results` is a tuple; read each element by position.
Print("All tasks complete: {Results(0)} | {Results(1)} | {Results(2)}")
Try it yourself
- Place this device on your island.
- Play the level and open the Verse log output.
- Watch the order: all three "started" lines print together, then the tasks finish in
0.2s -> 0.5s -> 1.0sorder — but the final "All tasks complete" line appears only once, after about 1 second. - Experiment: change the sleeps to 3.0, 2.0, and 1.0. The total wait is still only ~3.0 seconds (the slowest), not 6.0. Then try moving the three calls onto separate lines without
syncandSleepeach in turn — you'll see the total balloon to the sum.
Recap
sync:runs multiple async expressions at the same time.- It blocks until all inner tasks complete — it's a barrier.
- It returns a tuple of results in source order; read them with
Results(0),Results(1), etc. syncrequires a<suspends>context, and async work likeSleepis what makes parallelism meaningful.- Use it for independent initialization steps or concurrent waits where total time should equal the slowest task.
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 Parallel Execution with sync() 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.