Menu
CoddyTech

Абстрактные компоненты

Часть раздела Архитектура игр в Unity путешествия по Unity на Coddy. Урок 3 из 50.

Некоторые базовые классы описывают тип объекта, который никогда не существует сам по себе. Каждое оружие стреляет, но оружие, которое не является ни пистолетом, ни дробовиком, не может стрелять. Пометьте такой класс как abstract, а каждый шаг, который должны реализовать его подклассы, объявите абстрактным методом без тела:

public abstract class Weapon : MonoBehaviour
{
    public int shots;

    public void Pull()
    {
        shots++;
        Fire();
    }

    protected abstract void Fire();
}
public class Shotgun : Weapon
{
    public GameObject pelletPrefab;

    protected override void Fire()
    {
        for (int i = -1; i <= 1; i++)
        {
            Instantiate(pelletPrefab, transform.position + transform.right * i * 0.3f, transform.rotation);
        }
    }
}

Подкласс, в котором не реализован Fire, не компилируется: CS0534, 'Pistol' does not implement inherited abstract member 'Weapon.Fire()'. Unity также не позволяет добавить абстрактный скрипт на объект. Перетащите Weapon на объект, и Unity выдаст сообщение Can't add script behaviour 'Weapon'. The script class can't be abstract!, поскольку Unity не может создать Weapon без Fire.

Другие скрипты по-прежнему работают с базовым типом. GetComponent<Weapon>() возвращает подкласс, который находится на объекте, а Pull() запускает Fire этого подкласса:

// Player.cs
private Weapon weapon;

void Start()
{
    weapon = GetComponent<Weapon>();
}

void Update()
{
    if (Mouse.current.leftButton.wasPressedThisFrame)
    {
        weapon.Pull();
    }
}

Замените компонент Shotgun на Pistol — и скрипт Player останется прежним.

challenge icon

Задание

Легко

Башня волшебника поражает монстров на поле. В Monster.cs хранится то, что есть у каждого монстра: hp (3) и Zap(), который отнимает 1 hp, уничтожает монстра при 0, а в противном случае вызывает React(). Slime.cs реагирует, уменьшаясь. У Imp.cs нет реакции, а Monster передаёт ему пустой React, поэтому ничего не указывает на то, что реакция отсутствует.

  • Сделай Monster абстрактным классом, а React — абстрактным методом, чтобы монстр, который не указывает, как он реагирует, не компилировался. Тогда компилятор укажет на Imp.
  • Напиши React для Imp: он отпрыгивает на 2 единицы назад, подальше от башни (вдоль +z).
  • В Tower.cs при нажатии Space получай компонент Monster каждого объекта с тегом Monster, независимо от его типа, и вызывай у него Zap().

Нажми Play и поражай монстров, затем нажми Check.

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

using UnityEngine;

// Что общего у всех монстров.
public class Monster : MonoBehaviour
{
    public int hp = 3;

    public void Zap()
    {
        hp--;
        if (hp <= 0)
        {
            Destroy(gameObject);
        }
        else
        {
            React();
        }
    }

    // Как монстр этого вида реагирует на удар током, после которого выживает.
    protected virtual void React()
    {
    }
}
quiz iconПроверьте себя

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

Все уроки раздела Архитектура игр в Unity