Menu
CoddyTech

Награды

Урок 13 из 25 курса Игра на Unity: Tower Defense на Coddy.

Каждый враг, которого башня уничтожает, приносит ей reward. Enemy сообщает об убийстве так же, как сообщает о достижении базы: с помощью статического события Killed, а GameManager слушает его и добавляет деньги.

За убийство нужно платить один раз. Destroy не удаляет объект сразу: это происходит в конце кадра, и до тех пор он всё ещё находится в игре. Два выстрела могут попасть в цель в одном кадре, и второй обнаружит врага с 0 здоровья, который всё ещё на месте. Если TakeDamage сообщает об убийстве каждый раз, когда здоровье равно 0 или ниже, второй выстрел снова принесёт награду. В игре с воздушными шариками и дротиками возникает та же проблема, и её решает bool:

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

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

Врагу не нужен дополнительный bool, поскольку его здоровье уже показывает, мёртв ли он: если TakeDamage обнаруживает, что здоровье равно 0 или ниже, ему больше нечего делать.

challenge icon

Задание

Средне

За каждое убийство врага выдаётся награда.

  1. В Enemy добавь public static event Action<Enemy> Killed; и вызывай это событие в TakeDamage прямо перед уничтожением врага.
  2. Начни TakeDamage с if (health <= 0) return;, чтобы награда за убийство выдавалась один раз.
  3. В GameManager добавь public void Earn(int amount) (добавь сумму и отобрази её), а также подпишись на Enemy.Killed, чтобы получать enemy.data.reward.

Нажми «Играть»: количество денег будет расти, пока работают башни. Затем нажми «Проверить».

Попробуйте сами

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 iconПроверьте себя

В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.

Все уроки раздела Игра на Unity: Tower Defense

Потренируйтесь самостоятельно: Песочница Unity