Доберитесь до базы
Урок 3 из 18 курса Игра в Unity: защита башен на Coddy.
Враг, дошедший до последней контрольной точки, достиг базы: игрок теряет жизни, а враг исчезает. Жизни принадлежат GameManager, который отображает их на экране. Врагу не нужна ссылка на GameManager, чтобы сообщить об этом: вскоре враги будут создаваться десятками из префаба, а префаб не может ссылаться на объект в сцене.
Статическое событие решает обе проблемы. Оно принадлежит классу Enemy, а не отдельному врагу, поэтому GameManager подписывается один раз и получает сообщения от каждого врага, в том числе от созданных позже. Каждый враг вызывает это событие, передавая себя в качестве аргумента, чтобы слушатель мог узнать, какой вид врага прорвался. Монета в платформере сообщает о себе таким же образом:
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;
}Статическое событие существует, пока работает игра, поэтому -= важен как никогда: на уничтоженный ScoreBoard, от которого так и не отписались, всё ещё будут вызываться методы, и его код завершится с ошибкой при обращении к уничтоженному текстовому объекту. OnEnable и OnDisable идут парами, поэтому каждому += соответствует свой -=.
Задание
ЛегкоНа базе должны быть жизни, и враг, добравшийся до неё, должен их отнимать.
- В
EnemyDataдобавь публичное целое числоdamage: столько жизней этот тип врагов отнимает у базы. - В
Enemyобъяви публичное статическое событиеReachedBase, которое передаёт врага (Action<Enemy>). Когда враг достигает последней путевой точки, вызови это событие, передав в него самого врага, и уничтожь его, вместо того чтобы останавливаться там. - В
GameManagerдобавь сериализованное целое числоstartLives(20) и приватное целое числоlives, начальное значение которого равно этому числу. Подпишись наEnemy.ReachedBaseвOnEnableи отпишись вOnDisable. Каждый прошедший враг отнимает у базы значениеdamageсвоего ресурса. - Отображай количество жизней в сериализованном
TMP_TextlivesTextв видеLives: 20в начале и после каждого изменения.
На объекте Game есть компонент GameManager, в Inspector привязан LivesText, а каждый из двух ресурсов отнимает 1 жизнь. Нажми Play, дождись, пока оба врага доберутся до базы, затем нажми Check.
Попробуйте сами
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++;
}
}
}
В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.