Stop the Music, Start the Chaos: Configuring Waves in Verse
Unverified — this example may not compile as-is.
The Verse code below did not pass our automated compile check, so it isn't marked verified and is hidden from the guide listing. The explanation may still be useful, but treat the code as a draft and adapt it before use.
Stop the Music, Start the Chaos: Configuring Waves in Verse
You've got the island looking slick, but let's be real: if every enemy spawns at the exact same time with the same loot, you're not building a game—you're building a waiting room. Fortnite Creative is all about pacing. You need tension, release, escalation, and that sweet, sweet panic when Wave 3 hits and you realize you're out of ammo.
In this tutorial, we're going to ditch the static "spawn everything at once" approach. We're going to build a Wave Manager using Verse. Think of this as your personal Battle Bus pilot who doesn't just drop you off, but decides when the storm closes in and who shows up to meet you. We'll configure distinct waves, manage the flow of combat, and make sure your island feels alive, not like a broken record.
What You'll Learn
- Variables as Game State: How to track which wave the player is currently surviving.
- Functions as Actions: Creating reusable blocks of code for "Start Wave," "Spawn Enemies," and "End Wave."
- Events as Triggers: Connecting Verse logic to in-game devices (like Timers and Spawners) so they talk to each other.
- Scene Graph Basics: Understanding how your Verse script "sees" the devices in your island.
How It Works
Imagine you're designing a dungeon. You don't just throw 100 skeletons in at once. You set up a rhythm:
- Wave 1: Two weak husks. Easy.
- Wave 2: Five husks and a boss. Harder.
- Wave 3: Chaos. Everything spawns.
In Verse, we replicate this rhythm using Variables and Functions.
The Concept: Variables are Your HUD Stats
In Fortnite, you have a shield bar, a health bar, and a kill count. These change during the game. In programming, a Variable is just a named box that holds a value that can change.
- Game Analogy: Your Shield is a variable. It starts at 100. You take damage, it goes down. You use a medkit, it goes up.
- Verse Application: We'll create a variable called
CurrentWave. It starts at1. When Wave 1 ends, we change it to2.
The Concept: Functions are Your Loadout
You don't reload your gun by manually inserting each bullet one by one every time. You have a "Reload" action. In programming, a Function is a saved set of instructions that you can "call" or "trigger" whenever you want.
- Game Analogy: The "Reload" button on your controller. You press it, and the game handles the animation, the sound, and the ammo count.
- Verse Application: We'll write a function called
StartWave. When called, it will hide the "Next Wave" sign, turn on the spawner, and start the timer.
The Concept: Direct Event Binding is the Cables
In UEFN, you connect devices with cables. In Verse, we do something similar but with code. We Bind an event (like "Timer Finished") to a function (like "Spawn Next Wave"). This tells Verse: "When this timer hits zero, run this specific block of code."
Let's Build It
We are going to build a system where:
- A Billboard tells you which wave is next.
- A Button starts the wave.
- A Timer counts down the wave duration.
- When the timer ends, the wave "cleans up" and prepares the next one.
The Setup (Before Coding)
- Place a Billboard in your island. Name it
WaveInfo. Set the text to "Press Start for Wave 1". - Place a Button. Name it
StartWaveBtn. - Place a Timer. Name it
WaveTimer. Set the Duration to10.0seconds (for testing). - Place a Creature Spawner. Name it
EnemySpawner. Set it to Disabled initially. - Add a Verse Device to your island. Open the script editor.
The Verse Code
Copy this into your Verse file. Don't worry if it looks scary; we're breaking it down line-by-line.
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/Diagnostics }
using { /Verse.org/Localization }
# 2. THE SCRIPT CLASS: This is your "Island"
wave_controller := class(creative_device):
# 3. REFERENCES: Connecting our code to the devices in the world
# Think of these as "cables" from the code to the device
# Select the matching device in the UEFN Details panel for each property
@editable
WaveInfoBillboard : billboard_device = billboard_device{}
@editable
StartButton : button_device = button_device{}
@editable
WaveTimer : timer_device = timer_device{}
@editable
EnemySpawner : creature_spawner_device = creature_spawner_device{}
# 4. VARIABLES: Tracking our game state
var CurrentWave : int = 0
MaxWaves : int = 3
# 6. BINDING EVENTS: Connecting the triggers to the functions
# OnBegin runs automatically when the game session starts
OnBegin<override>()<suspends> : void =
# When the button is pressed, start the wave
StartButton.InteractedWithEvent.Subscribe(OnStartButtonPressed)
# When the timer finishes, end the wave
WaveTimer.SuccessEvent.Subscribe(OnWaveTimerFinished)
# Show the initial prompt on the billboard
WaveInfoBillboard.SetText(LocalizeMessage("Press Button for Wave 1"))
# Wrapper so the button event signature (agent) feeds into StartWave
OnStartButtonPressed(Agent : agent) : void =
StartWave()
# Wrapper so the timer event signature (agent) feeds into EndWave
OnWaveTimerFinished(Agent : ?agent) : void =
EndWave()
# 5. FUNCTIONS: The logic for what happens
# Function to Start a Wave
StartWave() : void =
# Update the variable
set CurrentWave = CurrentWave + 1
# Check if we've passed the max waves
if (CurrentWave > MaxWaves):
WaveInfoBillboard.SetText(LocalizeMessage("All Waves Complete! Victory!"))
return # Stop here, don't start another wave
# Update the Billboard text
WaveInfoBillboard.SetText(LocalizeMessage("Wave {CurrentWave} Starting!"))
# Enable the spawner so enemies can appear
EnemySpawner.Enable()
# Start the timer for this wave
WaveTimer.Start()
# Function to End a Wave (Called when timer finishes)
EndWave() : void =
# Disable the spawner so no more enemies spawn
EnemySpawner.Disable()
# Reset the timer for the next round
WaveTimer.Reset()
# Update the billboard to prompt the player
if (CurrentWave < MaxWaves):
WaveInfoBillboard.SetText(LocalizeMessage("Press Button for Wave {CurrentWave + 1}"))
else:
WaveInfoBillboard.SetText(LocalizeMessage("Final Wave Cleared! You Win!"))```
### Walkthrough: What Just Happened?
1. **Imports:** We told Verse, "Hey, I want to use devices from Fortnite's library." It's like saying, "I need my controller, my gun, and my medkit."
2. **Script Class & References:** This is the **Scene Graph** in action. The `wave_controller` is the brain. The lines marked `@editable` expose each device slot in the UEFN **Details** panel so you can drag your placed devices into them—exactly like plugging cables into sockets. If you rename a property here, update the Details panel assignment to match.
3. **Variables:** `CurrentWave` starts at `0`. Every time we call `StartWave`, we add `1` to it with the `set` keyword, which is how Verse mutates a `var`.
4. **Functions:**
* `StartWave()`: Increases the wave count, updates the text on the Billboard, turns on the spawner, and starts the timer.
* `EndWave()`: Turns off the spawner, resets the timer, and updates the text to tell the player to press the button again for the next wave.
5. **Binding:**
* `StartButton.InteractedWithEvent.Subscribe(OnStartButtonPressed)`: This is the magic. It says, "When the player clicks the button, run the `StartWave` function."
* `WaveTimer.SuccessEvent.Subscribe(OnWaveTimerFinished)`: This says, "When the 10-second timer hits zero, run the `EndWave` function."
## Try It Yourself
You've got the basics, but let's make it more interesting.
**Challenge:** Add a **Loot Granter** to your island. Configure it so that when `EndWave` runs (when the wave is cleared), it grants the player a specific item (like a Shield Potion or a Weapon).
**Hint:**
1. Place a **Loot Granter** device in your island.
2. Add it to your `wave_controller` script under the other references.
3. Inside the `EndWave` function, look up how to "Grant" an item to the player who triggered the timer. (Hint: Look at the `LootGranter` documentation for a function like `GrantTo` or similar, and see how you can get the player who triggered the event).
*Don't worry if you get stuck! The logic is the same: call the function, pass the player reference.*
## Recap
You just built a dynamic wave system. You learned how to:
* Use **Variables** to track game progress (Wave 1, Wave 2, etc.).
* Use **Functions** to group actions (Start Wave, End Wave).
* Use **Event Binding** to connect player input (Button Press) and game timing (Timer Finished) to your code.
Your island is no longer a static map—it's a living, breathing challenge that escalates as players progress. Now go make some waves.
## References
- https://dev.epicgames.com/documentation/en-us/fortnite/using-patchwork-instrument-player-devices-in-fortnite-creative
- https://dev.epicgames.com/documentation/en-us/fortnite-creative/using-patchwork-instrument-player-devices-in-fortnite-creative
- https://dev.epicgames.com/documentation/en-us/fortnite-creative/using-patchwork-lfo-modulator-devices-in-fortnite-creative
- https://dev.epicgames.com/documentation/en-us/fortnite/using-patchwork-lfo-modulator-devices-in-fortnite-creative
- https://dev.epicgames.com/documentation/en-us/fortnite/timer-device-design-examples-in-fortnite
Verse source files
- 01-device.verse · device
Turn this into a guided course
Add Configure the Different Waves 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.
References
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.