Wave Spawner
Wave Spawner
This scriptable object provides configuration for the various waves used when the Runtime Spawner has Wave Spawning enabled.
To Create a new Wave Spawner config you can Right Click in the Project window and go to ‘Create Other ⇒ Runtime Spawner ⇒ Wave Spawner’
Or use the Assets menu (Create ⇒ Runtime Spawner ⇒ Wave Spawner)
This will create an empty Wave Spawner, as shown below:

Click the ‘+’ button to create new Waves.
Below is a screenshot of a populated Wave Spawner

Properties (WaveSpawner)
Description Free‑form text for identifying the spawner (queryable in‑game).
Spawn Delay (
float 0..10
) Initial delay before the first wave starts.Wave Interval (
float 0..10
) Delay inserted after a wave completes (including any looping) and before the next wave starts.Waves (
List<WaveEntry>
) The ordered list of waves. Use + to add waves.
Validation: On edit, each wave auto-fills its name if blank and clamps counts (see below).
Wave Configuration (WaveEntry)
Wave Info
Name (
string
) Display name. If blank, auto‑fills toWave {index+1}
.Description (
string
) Optional, queryable in‑game.
Wave Timing
Spawn Delay (
float 0..10
) Delay before this wave begins.Spawn Instance Interval (
float 0..10
) Delay between spawning each agent within this wave.Spawn Count Min / Max (
int 1..100
) A random inclusive count in[Min, Max]
is chosen when the wave runs.spawnCountMin
is clamped to ≥ 1.spawnCountMax
is clamped to ≥spawnCountMin
.
Loop Policy (per wave)
Defined by LoopPolicy
:
Type (
LoopType
)None – Run the wave once (legacy behavior).
Duration – Repeat the wave until
durationSeconds
have elapsed.MaxLoops – Repeat the wave up to
maxLoops
times.0 means unlimited (no cap).
UntilSignal – Repeat until a signal with id
untilSignal
is received.
durationSeconds (
float ≥ 0
) Used whenType = Duration
.maxLoops (
int ≥ 0
) Used whenType = MaxLoops
(0 = unlimited).untilSignal (
string
) Used whenType = UntilSignal
; integrates with your signal bus.restSeconds (
float ≥ 0
) Optional pause between loop iterations (applies to all loop types exceptNone
since it doesn’t loop).shuffleOnLoop (
bool
) When true, each loop iteration shuffles the wave’s valid spawn entries and then cycles through that shuffled order without immediate repeats.
Loop execution specifics (from WaveTableRunner
+ WaveSpawnLoop
)
WaveTableRunner
+ WaveSpawnLoop
)Table-level Spawn Delay runs once before the first wave.
For each wave:
If
Type = None
: wave runs once.Otherwise: the runner calls the wave executor repeatedly, enforcing:
Duration
: stop when elapsed time ≥durationSeconds
.MaxLoops
: stop whenloops ≥ maxLoops
(unless 0 = unlimited).UntilSignal
: stop when the signal bus reports theuntilSignal
was fired.
restSeconds
is inserted between iterations of the same wave.
After a wave (and its loops) finishes, table-level Wave Interval is applied before the next wave.
Wave Spawners
Spawners (
List<SpawnEntry>
) The spawn configurations used by this wave. See Spawn Entry docs for fields.
Runtime behavior notes
Validation of entries: entries that are
null
or missing aprefab
are skipped with a warning and won’t be selected.Spawn count selection: the chosen count respects inclusive Max (internally handled with the exclusive
Random.Range
overload).Entry selection within a run:
With shuffleOnLoop = true: the executor Fisher–Yates shuffles the local list and then walks it in order (
spawned % count
), preventing immediate repeats until the list cycles.With shuffleOnLoop = false: each spawn picks a random valid entry.
Spawn points: if the initiating WaveTrigger provides
WaveSpawnPoints
, those are preferred; otherwise, the spawner uses the trigger (or owner) transform with a default range. (SeeWaveTrigger
docs for configuring explicit wave spawn points.)
Editor Validation (OnValidate)
For each wave:
Auto‑names if blank (
Wave {index+1}
).Clamps counts to valid ranges (
Min ≥ 1
,Max ≥ Min
).
Signal Bus Integration
The Loop Policy UntilSignal
mode relies on a lightweight static SignalBus system.
This allows a wave to repeat until a specific string signal is fired by your game logic.
How it works
Signals are string IDs.
Once a signal is fired, it stays latched until it is consumed or explicitly cleared.
The
WaveTableRunner
checksSignalBus.WasFired(untilSignal)
each loop.If the signal has been fired, the wave loop ends.
By default,
WasFired
consumes the signal (removes it from the fired set).
API Summary
SignalBus.Fire(string id)
Latches a signal by ID. No-op ifid
is null/empty.SignalBus.WasFired(string id, bool consume = true)
Returnstrue
if the signal was previously fired. Ifconsume = true
(default), the signal is cleared after the check.SignalBus.Clear(string id)
Clears the fired state of a specific signal.SignalBus.ClearAll()
Clears all fired signals.
Usage Example
// Somewhere in your gameplay logic:
if (bossDefeated)
SignalBus.Fire("BossDefeated");
// In a wave config:
loopPolicy.type = LoopType.UntilSignal;
loopPolicy.untilSignal = "BossDefeated";
In this example, the wave will keep repeating until your game logic fires the "BossDefeated"
signal.
Last updated