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
Hard- In
WaveSpawner, add the serialized fieldscountdownText(a TMP_Text) andnextWaveButton(a GameObject), andpublic void CallNextWave(), which the button calls to ask for the wave now. - Replace the wait before each wave with a countdown, run with
yield return StartCoroutine(Countdown());. While it runs, the button shows and the text readsNext 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. - Add
public event Action<int, int> WaveStarted, raised with the wave's number (from 1) and the number of waves when a wave starts. - In
GameManager, add the serialized fieldsspawner(a WaveSpawner) andwaveText(a TMP_Text), subscribe to WaveStarted, and showWave 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");
}
}
This lesson includes a short quiz. Start the lesson to answer it and track your progress.