События управляют UI
Часть раздела Архитектура игр в Unity путешествия по Unity на Coddy. Урок 15 из 64.
Благодаря событиям интерфейс следует за игрой, а игра ничего не знает об интерфейсе. Этот компонент Health хранит очки здоровья и сообщает о двух событиях: здоровье изменилось и достигло 0. В нём нет поля для полосы, текста или экрана завершения игры, поэтому один и тот же компонент работает на игроке, на противнике без интерфейса и в тестовой сцене:
public class Health : MonoBehaviour
{
public int maxHp = 100;
public event Action<int, int> OnChanged;
public event Action OnDied;
public int Hp { get; private set; }
void Awake()
{
Hp = maxHp;
}
public void TakeDamage(int amount)
{
if (Hp == 0) return;
Hp = Mathf.Max(Hp - amount, 0);
OnChanged?.Invoke(Hp, maxHp);
if (Hp == 0) OnDied?.Invoke();
}
}// HealthBar.cs, на HUD
public Health health;
public Image bar;
void OnEnable() { health.OnChanged += Show; }
void OnDisable() { health.OnChanged -= Show; }
void Start()
{
Show(health.Hp, health.maxHp);
}
void Show(int hp, int max)
{
bar.fillAmount = (float)hp / max;
}Полоса подписывается на событие, только пока она активна, с помощью пары OnEnable и OnDisable. Событие передаёт оба числа, поэтому Show больше ничего не нужно от компонента Health. GameOverScreen подписывается на OnDied, чтобы показать свою панель, а звук получения урона подписывается на OnChanged — каждое в собственном скрипте; компонент Health при этом не меняется ни для одного из них. Hp { get; private set; } позволяет интерфейсу читать здоровье, но не изменять его.
Событие сообщает об изменениях, поэтому до первого попадания полоса ничего не слышала. Она один раз отображает текущее здоровье в Start. Не в OnEnable: Unity вызывает Awake, а затем OnEnable для каждого объекта по отдельности, без гарантированного порядка, поэтому OnEnable полосы может выполниться до того, как Awake компонента Health установит Hp, и полоса покажет 0. К моменту запуска любого Start все вызовы Awake уже выполнены.
Задание
ЛегкоПусть оружие сообщает об изменениях, а HUD их отслеживает.
- В
Gun.csдобавьusing System;,public event Action<int, int> OnAmmoChangedиpublic event Action<bool> OnReloading; вызывай их в местах, указанных в комментариях. - В
AmmoHud.csподпишись вOnEnableи отпишись вOnDisable:ammoTextпоказываетAmmo: 4/6, аreloadTextотображается только во время перезарядки. - В
Startодин раз отобразиgun.Ammoиgun.Reloading.
Нажми «Играть» и дважды разряди оружие. Затем нажми «Проверить».
Попробуйте сами
using UnityEngine;
using TMPro;
public class AmmoHud : MonoBehaviour
{
public Gun gun;
public TMP_Text ammoText;
public GameObject reloadText;
}
Все уроки раздела Архитектура игр в Unity
1Компоненты, а не иерархии
Небольшие компонентыБазовый скрипт врагаАбстрактные компонентыКомпоненты работают вместеПовторение: модульная турельПовторение: спаренная пушка4Сериализованные данные
Сериализуемые классыСписки в инспектореПеречисления в инспектореПовторение: таблица добычиПовторение: определяем добычу2Интерфейсы в Unity
IDamageableИнтерфейсы и TryGetComponentGetComponentsПовторение: клавиша взаимодействияПовторение: ближайший в пределах досягаемости5ScriptableObjects
Ресурсы данныхХарактеристики оружияОбщие настройкиСохраняем ветерВолны как данныеПовторение: база предметовПовторение: покупка в магазинеПотренируйтесь самостоятельно: Песочница Unity