Menu
CoddyTech

Reach the Base

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

An enemy that walks onto the last waypoint has reached the base: the player loses lives and the enemy goes. The lives belong to the GameManager, which shows them on screen. The enemy should not need a reference to the GameManager to report it: soon the enemies are made by the dozen from a prefab, and a prefab cannot point at an object in the scene.

A static event solves both. It belongs to the Enemy class, not to one enemy, so the GameManager subscribes once and hears from every enemy, also from ones spawned later. Each enemy raises it with itself as the argument, so the listener can read which kind got through. A coin in a platformer reports the same way:

public class Coin : MonoBehaviour
{
    public static event Action<Coin> Collected;
    public int value = 1;

    void OnTriggerEnter(Collider other)
    {
        Collected?.Invoke(this);
        Destroy(gameObject);
    }
}
// ScoreBoard.cs
void OnEnable()
{
    Coin.Collected += AddCoin;
}

void OnDisable()
{
    Coin.Collected -= AddCoin;
}

void AddCoin(Coin coin)
{
    score += coin.value;
}

A static event lives as long as the game, so the -= matters more than ever: a destroyed ScoreBoard that never left would still be called, and its code would fail on its destroyed text. OnEnable and OnDisable come in pairs, so each += gets its -=.

challenge icon

Challenge

Easy

The base needs lives, and an enemy that reaches it must cost them.

  1. In EnemyData, add a public int damage: the lives this kind takes from the base.
  2. In Enemy, declare a public static event ReachedBase that passes the enemy (Action<Enemy>). When the enemy arrives on the last waypoint, raise it with itself and destroy the enemy, instead of stopping there.
  3. In GameManager, add a serialized int startLives (20) and a private int lives that starts there. Subscribe to Enemy.ReachedBase in OnEnable and unsubscribe in OnDisable. Each enemy that gets through takes its asset's damage off the lives.
  4. Show the lives in a serialized TMP_Text livesText, as Lives: 20, at the start and after every change.

The Game object has the GameManager, the Inspector links the LivesText, and both assets take 1 life. Press Play, wait for both enemies to reach the base, then Check.

Try it yourself

using UnityEngine;

public class Enemy : MonoBehaviour
{
    public EnemyData data;
    public Transform[] waypoints;

    private int next = 1;
    private int health;

    void Awake()
    {
        health = data.maxHealth;
    }

    void Update()
    {
        if (next >= waypoints.Length)
        {
            return;
        }

        Vector3 target = waypoints[next].position;
        transform.position = Vector3.MoveTowards(transform.position, target, data.speed * Time.deltaTime);
        if (transform.position == target)
        {
            next++;
        }
    }
}
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