Menu
CoddyTech

Waves as Data

Part of the Game Architecture in Unity section of Coddy's Unity journey. Lesson 27 of 64.

A level's waves are a list: three grunts, then two brutes, then a boss. Written in a spawner's code, every level needs its own code. Written as data, the list goes into an asset, one asset per level, and one spawner script reads whichever asset it is given. Each entry is a [System.Serializable] class, so the asset's Inspector shows the list:

using System.Collections.Generic;
using UnityEngine;

[System.Serializable]
public class Wave
{
    public GameObject enemy;
    public int count = 1;
    public float spacing = 1f;
}

[CreateAssetMenu(menuName = "Game/Wave Set")]
public class WaveSet : ScriptableObject
{
    public List<Wave> waves;
    public float restBetweenWaves = 3f;
}

This is all one file, WaveSet.cs: the ScriptableObject needs a file of its own name, and the plain Wave class can sit beside it. Select a WaveSet asset and the Inspector shows Waves with its Size and the rows Element 0, Element 1, each with Enemy, Count and Spacing; the + button adds a wave. The spawner walks the list in a coroutine:

public class WaveSpawner : MonoBehaviour
{
    public WaveSet waveSet;

    void Start()
    {
        StartCoroutine(SendWaves());
    }

    IEnumerator SendWaves()
    {
        foreach (Wave wave in waveSet.waves)
        {
            for (int i = 0; i < wave.count; i++)
            {
                Instantiate(wave.enemy, transform.position, Quaternion.identity);
                yield return new WaitForSeconds(wave.spacing);
            }
            yield return new WaitForSeconds(waveSet.restBetweenWaves);
        }
        Debug.Log("Last wave sent");
    }
}

With Level1 holding 3 grunts 0.5 seconds apart and then 2 brutes, the grunts come at 0, 0.5 and 1 second, the spacing after the last grunt and the 3 second rest follow, and the first brute comes at 4.5 seconds. Level 2's spawner gets a Level2 asset with harder waves, and the script stays the same.

challenge icon

Challenge

Medium

Turn the Dropper's rhythm into a song asset.

  1. In DropPattern.cs, write a [System.Serializable] class Drop with public int lane and float delay.
  2. Below it, write DropPattern : ScriptableObject with [CreateAssetMenu] and public GameObject blockPrefab, float laneWidth, List<Drop> drops.
  3. In Dropper, use public DropPattern pattern;: per drop, wait drop.delay, then drop the block moved drop.lane * pattern.laneWidth along x.

Press Play: four blocks fall. Then Check.

Try it yourself

using System.Collections.Generic;
using UnityEngine;

// Drop (one block: its lane and the wait before it) and DropPattern (the asset) go here

All lessons in Game Architecture in Unity

Practice on your own: Unity playground