Shuffle in Verse: Randomizing Arrays for Unpredictable Gameplay
Every time a player docks at your sun-drenched cove, the treasure chest order should feel fresh. Verse's built-in `Shuffle` function from `/Verse.org/Random` takes any array and returns a new array with the same elements in a random order — no manual Fisher-Yates needed. Master it once and every loot table, spawn sequence, and quiz question on your island becomes endlessly replayable.
shuffle_array in ~90 seconds.Overview
The Shuffle function lives in the /Verse.org/Random module alongside GetRandomInt and GetRandomFloat. It solves a classic game-design problem: you have a fixed set of things, but you want players to encounter them in a different order every time.
Common uses on a Fortnite island:
- Randomize which item spawner activates first at a beach loot drop
- Shuffle the order of cinematic sequences in an intro cutscene
- Pick a random subset of score bonuses for a timed challenge
- Rotate which pressure plate triggers a vault door each round
Signature (from /Verse.org/Random):
Shuffle<public>(Input: []t where t: type)<transacts>: []t
Shuffle is a generic, pure function — it takes any typed array and returns a new shuffled array. The original array is unchanged. Because it is <transacts>, it can be called inside speculative (if) contexts without side effects.
API Reference
(API surface could not be resolved for this device.)
Walkthrough
Scenario: A sunny clifftop dock has four item spawners arranged along the pier. Each round, the spawners activate in a random order, one per second, so players can never memorise the loot pattern. A cinematic sequence plays after all spawners have fired.
using { /Fortnite.com/Devices }
using { /Verse.org/Random }
using { /Verse.org/Simulation }
# Place this device on your island, then wire up the four @editable fields
# in the UEFN details panel.
dock_loot_shuffler := class(creative_device):
# Four item spawners placed along the clifftop pier
@editable
Spawner0 : item_spawner_device = item_spawner_device{}
@editable
Spawner1 : item_spawner_device = item_spawner_device{}
@editable
Spawner2 : item_spawner_device = item_spawner_device{}
@editable
Spawner3 : item_spawner_device = item_spawner_device{}
# Cinematic that plays after all loot has dropped
@editable
OutroCinematic : cinematic_sequence_device = cinematic_sequence_device{}
# Score manager awards a bonus for watching the full drop
@editable
BonusScore : score_manager_device = score_manager_device{}
OnBegin<override>()<suspends> : void =
# 1. Build an ordered array of all four spawners
Spawners : []item_spawner_device = array:
Spawner0
Spawner1
Spawner2
Spawner3
# 2. Shuffle returns a NEW array — original Spawners is untouched
ShuffledSpawners : []item_spawner_device = Shuffle(Spawners)
# 3. Activate each spawner in the shuffled order, one per second
for (S : ShuffledSpawners):
S.SpawnItem() # Spawn the item at this spawner's location
Sleep(1.0) # Wait 1 second before the next drop
# 4. All loot dropped — play the victory cinematic for everyone
OutroCinematic.Play()
# 5. Wait for the cinematic to finish, then award the score bonus
OutroCinematic.StoppedEvent.Await()
BonusScore.Activate()```
**Line-by-line breakdown:**
| Lines | What's happening |
|---|---|
| `Spawners := array{...}` | Collects the four `@editable` spawners into a typed `[]item_spawner_device`. |
| `Shuffle(Spawners)` | Returns a new array with the same four spawners in a random order. `Spawners` itself is unchanged. |
| `for (S : ShuffledSpawners)` | Iterates over every element in the shuffled result. |
| `S.Spawn()` | Calls the real `item_spawner_device` API to materialise the item in the world. |
| `Sleep(1.0)` | Suspends execution for one second so drops feel staggered, not simultaneous. |
| `OutroCinematic.Play()` | Fires the cinematic sequence device for all players. |
| `OutroCinematic.StoppedEvent.Await()` | Blocks until the cinematic ends before awarding score. |
| `BonusScore.Activate()` | Grants points via the score manager device. |
## Common patterns
### Pattern 1 — Shuffle a plain array of integers to pick a random question order
Useful for quiz minigames on your island where you have a fixed bank of questions stored as indices.
```verse
using { /Fortnite.com/Devices }
using { /Verse.org/Random }
using { /Verse.org/Simulation }
quiz_order_device := class(creative_device):
# One score manager per correct answer slot (5 questions)
@editable
Q0Score : score_manager_device = score_manager_device{}
@editable
Q1Score : score_manager_device = score_manager_device{}
@editable
Q2Score : score_manager_device = score_manager_device{}
# Helper: returns the score device for a given question index
GetScoreDevice(Index : int) : score_manager_device =
if (Index = 0):
Q0Score
else if (Index = 1):
Q1Score
else:
Q2Score
OnBegin<override>()<suspends> : void =
# Build an index array [0, 1, 2] then shuffle it
QuestionIndices : []int = array{0, 1, 2}
ShuffledIndices : []int = Shuffle(QuestionIndices)
# Activate score devices in the shuffled order with a 3-second gap
for (Idx : ShuffledIndices):
Device := GetScoreDevice(Idx)
Device.Enable()
Sleep(3.0)
Device.Disable()
Pattern 2 — Re-shuffle every round using a timer device
The timer fires at the end of each round; subscribe to SuccessEvent to trigger a fresh shuffle.
using { /Fortnite.com/Devices }
using { /Verse.org/Random }
using { /Verse.org/Simulation }
repeating_shuffle_device := class(creative_device):
@editable
RoundTimer : timer_device = timer_device{}
@editable
SpawnerA : item_spawner_device = item_spawner_device{}
@editable
SpawnerB : item_spawner_device = item_spawner_device{}
@editable
SpawnerC : item_spawner_device = item_spawner_device{}
# Called each time the round timer succeeds
OnRoundEnd(MaybeAgent : ?agent) : void =
# Shuffle the spawners and fire the first one immediately
Spawners : []item_spawner_device = array{SpawnerA, SpawnerB, SpawnerC}
ShuffledSpawners : []item_spawner_device = Shuffle(Spawners)
if (First := ShuffledSpawners[0]):
First.Spawn()
OnBegin<override>()<suspends> : void =
# Subscribe so every timer completion triggers a new shuffle
RoundTimer.SuccessEvent.Subscribe(OnRoundEnd)
# Start the first round
RoundTimer.Start()
# Keep the device alive
loop:
Sleep(60.0)
Pattern 3 — Shuffle cinematic sequences for a randomised intro at the cove dock
Three short cinematics play in a random order each time a player arrives, keeping the atmosphere fresh.
using { /Fortnite.com/Devices }
using { /Verse.org/Random }
using { /Verse.org/Simulation }
cove_intro_device := class(creative_device):
@editable
Intro0 : cinematic_sequence_device = cinematic_sequence_device{}
@editable
Intro1 : cinematic_sequence_device = cinematic_sequence_device{}
@editable
Intro2 : cinematic_sequence_device = cinematic_sequence_device{}
# Plays all three intros in a random order, waiting for each to finish
PlayShuffledIntros()<suspends> : void =
Intros : []cinematic_sequence_device = array{Intro0, Intro1, Intro2}
ShuffledIntros : []cinematic_sequence_device = Shuffle(Intros)
for (Seq : ShuffledIntros):
Seq.Play()
Seq.StoppedEvent.Await()
OnBegin<override>()<suspends> : void =
PlayShuffledIntros()
Gotchas
1. Shuffle returns a new array — it does NOT mutate the original
# WRONG mental model:
Shuffle(MyArray) # result is discarded — MyArray is unchanged!
# CORRECT:
Shuffled := Shuffle(MyArray) # capture the return value
Always assign the result to a new variable.
2. Indexing the shuffled result can fail — use if to unwrap
Array access in Verse is a failable expression. Always guard it:
if (First := ShuffledSpawners[0]):
First.Spawn()
# Without the `if`, the compiler will reject the bare index access
# in a non-failable context.
3. Shuffle requires the /Verse.org/Random import
Forgetting the import causes an Unknown identifier error:
using { /Verse.org/Random } # required — Shuffle lives here
4. The element type must be consistent — no mixed arrays
Shuffle is generic over t : type. All elements must be the same type. You cannot shuffle []item_spawner_device and []cinematic_sequence_device in the same call — create separate arrays for each device type.
5. Sleep inside a for loop requires <suspends> on the enclosing function
If you call Sleep while iterating a shuffled array, the function must be declared ()<suspends>. OnBegin already carries this effect, but any helper you extract must also declare it:
ActivateInOrder(Devices : []item_spawner_device)<suspends> : void =
for (D : Devices):
D.Spawn()
Sleep(1.0)
6. Shuffle is <transacts> — safe inside speculative contexts
Because Shuffle is marked <transacts>, you can call it inside an if block or other speculative context and rely on automatic rollback if the context fails. This is rarely needed but good to know.
Build your own lesson with shuffle_array
Generate a personalized, compile-checked lesson grounded in this exact reference.
Build a lesson →