Spawn Director
Overview
The Spawn Director controls the overall intensity curve of your encounter. Instead of every spawner behaving at a fixed difficulty, the director applies step-based multipliers that adjust pacing over time.
This lets designers “script” the escalation of tension without hand-authoring every wave.

Core Concepts
Intensity Profile
A ScriptableObject defining steps. Each step sets:
Concurrent Alive Cap – how many enemies can exist at once. Overrides the Max Global Population setting on the main Runtime Spawner.
Global Spawn Window – min/max delay between spawn events.
Spawn Rate Multiplier – speeds up or slows down all spawn rates.
Wave Rate Multiplier – adjusts timing between waves.
Advance Modes
Manual: Game code calls
StepUp(),StepDown(), orSetStep().Auto By Time: Steps advance automatically every N seconds.
Start Step Defines which step the director begins on.
Usage Patterns
Cinematic Escalation: Start at step 0 (calm), advance every 60s until reaching the climax step.
Dynamic Difficulty: Use game triggers (player health low, objective destroyed, etc.) to call
StepUp()orStepDown().Replayable Missions: Adjust profile assets per mission type, reusing the same director logic.
Also see:
Fundamentals
SpawnDirector drives spawn system intensity over time or via explicit step changes. It reads an IntensityProfile and applies its values to a bound RuntimeSpawner, tuning:
Global concurrent alive cap
Global population window
Global spawn rate multiplier
Wave interval multiplier
It provides a simple step-based interface for controlling pacing (early game, mid game, late game, final push, etc.).
Responsibilities
Bind to a
RuntimeSpawnerand update its tuning values.Apply a configurable
IntensityProfilewith multiple steps.Advance steps:
Automatically by time, or
Manually via API (
StepUp,StepDown,SetStep).
Notify listeners whenever the active step changes.
RuntimeSpawner calls into SpawnDirector during its own lifecycle to initialize and drive the director.
Requirements
A
RuntimeSpawnerin the scene.An
IntensityProfileasset with one or more steps, each defining:concurrentAliveCapglobalRange(min/max global population)spawnRateMultwaveRateMultAdvance mode and per-step timing (in the profile).
There is typically one SpawnDirector per gameplay session or scene.
Key Fields and Properties
Profile
public IntensityProfile ProfileThe profile that defines:
Step list (
steps)Advance mode (
AdvanceMode.ManualorAdvanceMode.AutoByTime)Timing (
secondsPerStepfor auto mode).
Can be assigned in the inspector or at runtime.
Step information
public int CurrentStep { get; }
public int MaxStep { get; }
public int StepsCount { get; }CurrentStepCurrent applied step index (0-based).MaxStepHighest valid step index (0-based), or0if the profile is empty.StepsCountNumber of steps defined by the profile, or0if none.
Events
public event Action<int> OnStepChanged;Raised whenever the active step changes. Payload: the new step index (0-based).
This event allows other systems (e.g. RegionPopulationController, UI, audio) to react in sync with spawn intensity.
Lifecycle (RuntimeSpawner integration)
SpawnDirector is controlled from RuntimeSpawner:
Init
public void Init(RuntimeSpawner spawner)Binds the director to the
RuntimeSpawnerinstance.Called from
RuntimeSpawner.Init().
Begin
public void Begin()Validates that both
ProfileandRuntimeSpawnerare set and that the profile has at least one step.Applies the starting step (
startStep, clamped to valid range).If the profile’s advance mode is
AutoByTime, starts an internal coroutine (AutoAdvance) to advance steps over time.Called from
RuntimeSpawner.StartSpawners().
Stop / Pause / Resume / End
public void Stop() // Alias for Pause
public void Pause()
public void Resume()
public void End()Pause()Stops auto-advance without resetting the current step.Resume()Restarts auto-advance from the current step if:A valid profile is present.
A spawner is bound.
The profile is configured for timed advance.
End()Fully stops the director and clears transient state (no step reset). Called fromRuntimeSpawner.StopSpawners()or equivalent when tearing down the session.
Step Control API
These methods provide manual control over the current step.
public void StepUp(int delta = 1)
public void StepDown(int delta = 1)
public void SetStep(int index)StepUp(delta)Increments the current step bydelta, clamped to the range[0, MaxStep].StepDown(delta)Decrements the current step bydelta, clamped to[0, MaxStep].SetStep(index)Sets the current step toindex, clamped to[0, MaxStep].
Each of these calls routes through ApplyStep, which:
Updates
_currentStep.Retrieves the step data from
Profile.steps[_currentStep].Invokes
OnStepChanged(_currentStep).Applies tuning to the bound
RuntimeSpawner:_spawner.SetConcurrentAliveCap(step.concurrentAliveCap);_spawner.SetGlobalSpawnWindow(step.globalRange.x, step.globalRange.y);_spawner.SetSpawnRateMultiplier(step.spawnRateMult);_spawner.SetWaveRateMultiplier(step.waveRateMult);
Auto-Advance Behaviour
When Profile.advance == IntensityProfile.AdvanceMode.AutoByTime:
private IEnumerator AutoAdvance()
{
while (enabled && profile)
{
yield return new WaitForSeconds(profile.secondsPerStep);
StepUp();
}
}Runs while the component is enabled and a profile is assigned.
Waits for
profile.secondsPerStepbetween step advances.Each tick calls
StepUp(), which clamps atMaxStep. (The profile defines whether to stop at the last step or if other behaviour is desired.)
Auto-advance can be paused/resumed via Pause() and Resume() and is started from Begin().
Typical Usage Patterns
1. Basic intensity progression over time
Configuration:
Create an
IntensityProfileasset (e.g.SurvivalProfile).Define several steps:
Step 0: low population, slow spawn rate.
Step 1: medium population, medium spawn rate.
Step 2: high population, fast spawn rate.
Set:
advance = AutoByTimesecondsPerStep = 60(for example).
In the scene:
Add
RuntimeSpawnerand configure spawn entries.Add
SpawnDirectorand assign:Profile = SurvivalProfilestartStep = 0
Ensure
RuntimeSpawnerfinds the director inInit()(this happens automatically if both are on the same GameObject, or via the existing discovery logic).
At runtime:
The spawner initializes and starts.
SpawnDirector.Begin()applies step 0.Every 60 seconds,
AutoAdvanceincreases the step:Step 1, then Step 2, adjusting:
MaxObjectCountGlobal min/max population
Spawn rates
Wave rates
2. Manual step control from game state
For a mission-driven or wave-based mode where steps are tied to objectives:
using UnityEngine;
using MegaCrush.Spawner;
public class MissionPacing : MonoBehaviour
{
[SerializeField] private SpawnDirector director;
public void OnObjective1Complete()
{
director.SetStep(1); // Medium intensity
}
public void OnObjective2Complete()
{
director.SetStep(2); // High intensity
}
public void OnBossPhase()
{
director.SetStep(director.MaxStep); // Final intensity
}
}Attach this script to an object managing mission flow.
Call
SetStepin response to mission events, cutscenes, or checkpoints.
3. Hooking other systems to step changes
Other systems can subscribe to OnStepChanged to adjust their own behaviour in sync with spawn intensity:
using UnityEngine;
using MegaCrush.Spawner;
public class IntensityHUD : MonoBehaviour
{
[SerializeField] private SpawnDirector director;
private void OnEnable()
{
if (director != null)
director.OnStepChanged += HandleStepChanged;
}
private void OnDisable()
{
if (director != null)
director.OnStepChanged -= HandleStepChanged;
}
private void HandleStepChanged(int step)
{
// Example: update HUD, music, or post-processing
Debug.Log($"Spawn intensity step changed to: {step}");
}
}Common uses:
Updating UI “Threat Level” indicators.
Blending music layers.
Adjusting non-spawn systems (e.g. loot quality, timer pressure) in lockstep with spawn difficulty.
4. Pausing and resuming intensity progression
If the game can be paused or enter a safe zone:
using UnityEngine;
using MegaCrush.Spawner;
public class PauseHandler : MonoBehaviour
{
[SerializeField] private SpawnDirector director;
public void OnGamePaused()
{
director.Pause();
}
public void OnGameResumed()
{
director.Resume();
}
}With this setup:
Auto-advance is stopped while the game is paused.
When the game resumes, the director continues advancing from the same step.
5. Switching profiles at runtime
To change pacing model (for example, between different difficulty modes):
using UnityEngine;
using MegaCrush.Spawner;
public class DirectorProfileSwitcher : MonoBehaviour
{
[SerializeField] private SpawnDirector director;
[SerializeField] private IntensityProfile normalProfile;
[SerializeField] private IntensityProfile hardProfile;
public void UseNormal()
{
director.Profile = normalProfile;
director.SetStep(0);
director.Resume();
}
public void UseHard()
{
director.Profile = hardProfile;
director.SetStep(0);
director.Resume();
}
}This allows the same scene to support multiple pacing profiles without changing the underlying spawn setup.
Last updated