Награды
Урок 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 или ниже, ему больше нечего делать.
Задание
СреднеЗа каждое убийство врага выдаётся награда.
- В
Enemyдобавьpublic static event Action<Enemy> Killed;и вызывай это событие вTakeDamageпрямо перед уничтожением врага. - Начни
TakeDamageсif (health <= 0) return;, чтобы награда за убийство выдавалась один раз. - В
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);
}
}
}
В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Игра на Unity: Tower Defense
Потренируйтесь самостоятельно: Песочница Unity