Базовый скрипт врага
Часть раздела Архитектура игр в Unity путешествия по Unity на Coddy. Урок 2 из 64.
В C# один класс может наследоваться от другого: class Ghost : Enemy получает все поля и методы Enemy и добавляет собственные. Метод, помеченный базовым классом как virtual, можно заменить в подклассе с помощью override, а base.Describe() запускает версию базового класса изнутри новой. Обычный код на C#:
class Enemy
{
protected int hp = 3;
public virtual string Describe()
{
return "Enemy with " + hp + " hp";
}
}
class Ghost : Enemy
{
public override string Describe()
{
return base.Describe() + ", see-through";
}
}Вызов Describe() у Ghost возвращает Enemy with 3 hp, see-through. protected означает, что Enemy и его подклассы могут использовать hp, а другие классы — нет.
В Unity у врагов большая часть кода общая: очки здоровья, скорость, способ передвижения. Этот код находится в базовом классе, который наследуется от MonoBehaviour, а каждый вид врагов наследуется от него. Этот Enemy задаёт очки здоровья в Start и движется в направлении, куда он обращён, в Update, а Ghost изменяет начало, чтобы двигаться в два раза быстрее:
public class Enemy : MonoBehaviour
{
public int maxHp = 3;
public float speed = 2f;
protected int hp;
protected virtual void Start()
{
hp = maxHp;
}
protected virtual void Update()
{
transform.Translate(Vector3.forward * speed * Time.deltaTime);
}
}public class Ghost : Enemy
{
protected override void Start()
{
base.Start();
speed *= 2f;
}
}Ghost наследует поля, поэтому в Inspector у Ghost отображаются maxHp и speed. Он также наследует Update, поэтому движется без собственного Update. hp имеет уровень доступа protected: Enemy и его подклассы могут использовать его, а другие скрипты — нет.
Unity находит Start и Update по имени независимо от уровня доступа и вызывает метод в наиболее производном классе. Если бы у Enemy был закрытый void Start(), а Ghost объявил свой, Unity вызвала бы только метод Ghost: метод Enemy никогда бы не выполнялся, а hp оставался бы равным 0 без ошибки. Объявление сообщений базового класса как protected virtual делает это обычным C#: подкласс пишет override, а base.Start() выполняет часть базового класса в месте вызова. Не укажешь этот вызов — часть базового класса будет пропущена. Так подкласс заменяет шаг, а не дополняет его.
Задание
ЛегкоСделай так, чтобы Golem и Wasp выполняли часть Enemy перед своей собственной.
- В
Enemyдобавьprotected virtualпередvoid Start()иvoid Update(). - В
Golemзамени объявление наprotected override void Start(), а первой строкой добавьbase.Start();. - В
Waspзамени объявление наprotected override void Update(), а первой строкой добавьbase.Update();.
Нажми «Играть»: голем марширует с полным запасом здоровья, а оса зигзагами движется во время марша. Затем нажми «Проверить».
Попробуйте сами
using UnityEngine;
// Что общего у всех монстров.
public class Enemy : MonoBehaviour
{
public int maxHp = 4;
public float speed = 1.5f;
protected int hp;
protected Vector3 spawnPoint;
void Start()
{
hp = maxHp;
spawnPoint = transform.position;
}
void Update()
{
// двигаться к замку вдоль оси z в отрицательном направлении
transform.position += Vector3.back * speed * Time.deltaTime;
}
}
Все уроки раздела Архитектура игр в Unity
1Компоненты, а не иерархии
Небольшие компонентыБазовый скрипт врагаАбстрактные компонентыКомпоненты работают вместеПовторение: модульная турельПовторение: спаренная пушка4Сериализованные данные
Сериализуемые классыСписки в инспектореПеречисления в инспектореПовторение: таблица добычиПовторение: определяем добычу2Интерфейсы в Unity
IDamageableИнтерфейсы и TryGetComponentGetComponentsПовторение: клавиша взаимодействияПовторение: ближайший в пределах досягаемости5ScriptableObjects
Ресурсы данныхХарактеристики оружияОбщие настройкиСохраняем ветерВолны как данныеПовторение: база предметовПовторение: покупка в магазинеПотренируйтесь самостоятельно: Песочница Unity