Menu
CoddyTech

Rewards

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

Every enemy a tower brings down pays its reward. The Enemy reports the kill the way it reports reaching the base, with a static event, Killed, and the GameManager listens and adds the money.

A kill must pay once. Destroy does not remove an object at once: it goes at the end of the frame, and until then it is still in the game. Two shots can land in the same frame, and the second finds an enemy at 0 health that is still there. If TakeDamage reports a kill every time the health is at 0 or below, that second shot pays again. A balloon game with darts has the same trap, and a bool closes it:

public void Pop()
{
    if (popped)
    {
        return;
    }

    popped = true;
    Popped?.Invoke(this);
    Destroy(gameObject);
}

The enemy needs no extra bool, since its health already says whether it is dead: a TakeDamage that finds the health at 0 or below has nothing left to do.

challenge icon

Challenge

Medium
  1. In Enemy, declare a public static event Killed (Action<Enemy>). Raise it with the enemy when TakeDamage brings its health to 0 or below, right before destroying it.
  2. A kill pays once: when TakeDamage is called on an enemy whose health is already 0 or below, it does nothing.
  3. In GameManager, add public void Earn(int amount), which adds to the money and shows it. Subscribe to Enemy.Killed next to ReachedBase, and earn the killed enemy's reward.

Press Play and watch the money grow as the towers work, then Check.

Try it yourself

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

public class Enemy : MonoBehaviour, IDamageable
{
    public static readonly List<Enemy> All = new List<Enemy>();
    public static event Action<Enemy> ReachedBase;

    public EnemyData data;
    public Transform[] waypoints;

    private int next = 1;
    private int health;

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

    void OnEnable()
    {
        All.Add(this);
    }

    void OnDisable()
    {
        All.Remove(this);
    }

    void Update()
    {
        Vector3 target = waypoints[next].position;
        transform.position = Vector3.MoveTowards(transform.position, target, data.speed * Time.deltaTime);
        if (transform.position == target)
        {
            next++;
            if (next == waypoints.Length)
            {
                ReachedBase?.Invoke(this);
                Destroy(gameObject);
            }
        }
    }

    public void TakeDamage(int amount)
    {
        health -= amount;
        if (health <= 0)
        {
            Destroy(gameObject);
        }
    }
}
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