Menu
CoddyTech

Next Wave

Lesson 17 of 18 in Coddy's Unity Game: Tower Defense course.

Between waves the player builds, and a countdown shows how long is left. A player who is ready can call the next wave early with a button. The break is a loop in a coroutine that yields null, so it runs once per frame: it counts the time left down, shows it, and ends when the time is up or when the button asked for the wave. The button only sets a bool, and the loop reads it:

while (left > 0f && !skipRequested)
{
    // show the seconds left, count down, wait a frame
}
skipRequested = false;

The bool is set back to false after it has been used, or every break after the first would end at once. Mathf.CeilToInt rounds up, so 2.3 seconds left reads 3, and the countdown says 1 for the whole last second rather than 0. The countdown is a coroutine of its own, and yield return StartCoroutine(Countdown()); runs it and waits for it to finish before the wave loop goes on.

The HUD also shows the wave number. The spawner knows it, and the GameManager shows it, so the spawner raises a C# event, WaveStarted, with the wave and the number of waves. Unlike the enemies' static events, it belongs to the one spawner, and the GameManager subscribes through its spawner field.

challenge icon

Challenge

Hard
  1. In WaveSpawner, add the serialized fields countdownText (a TMP_Text) and nextWaveButton (a GameObject), and public void CallNextWave(), which the button calls to ask for the wave now.
  2. Replace the wait before each wave with a countdown, run with yield return StartCoroutine(Countdown());. While it runs, the button shows and the text reads Next wave in 8, the seconds left rounded up. It ends when the time is up or the button was clicked; then the text is empty and the button hidden.
  3. Add public event Action<int, int> WaveStarted, raised with the wave's number (from 1) and the number of waves when a wave starts.
  4. In GameManager, add the serialized fields spawner (a WaveSpawner) and waveText (a TMP_Text), subscribe to WaveStarted, and show Wave 1/8.

The HUD has the WaveText, the CountdownText and the NextWaveButton. Press Play, build, and call the first wave early, then Check.

Try it yourself

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class WaveSpawner : MonoBehaviour
{
    [SerializeField] private List<Wave> waves = new List<Wave>();
    [SerializeField] private Transform[] waypoints;
    [SerializeField] private float timeBetweenWaves = 5f;

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

    IEnumerator RunWaves()
    {
        for (int i = 0; i < waves.Count; i++)
        {
            yield return new WaitForSeconds(timeBetweenWaves);
            Debug.Log("Wave " + (i + 1));
            Wave wave = waves[i];
            for (int n = 0; n < wave.count; n++)
            {
                Enemy enemy = Instantiate(wave.enemy, waypoints[0].position, Quaternion.identity);
                enemy.waypoints = waypoints;
                yield return new WaitForSeconds(wave.spacing);
            }
        }
        Debug.Log("All waves sent");
    }
}
quiz iconTest yourself

This lesson includes a short quiz. Start the lesson to answer it and track your progress.

All lessons in Unity Game: Tower Defense