IDamageable
Часть раздела Архитектура игр в Unity путешествия по Unity на Coddy. Урок 7 из 64.
Интерфейс — это список методов, которые класс обещает иметь, но без кода внутри них. Классы, у которых больше нет ничего общего, могут давать одно и то же обещание. На простом C#:
interface IGreeter
{
string Greet();
}
class Robot : IGreeter
{
public string Greet() { return "Beep"; }
}
class Cat : IGreeter
{
public string Greet() { return "Meow"; }
}Переменная типа IGreeter может содержать Robot или Cat, а вызов greeter.Greet() запускает метод того объекта, который она содержит. Класс, в котором указан IGreeter, но нет публичного метода Greet(), не скомпилируется.
В игре многие объекты могут получать урон, и у них мало общего: у игрока есть очки здоровья, а ящик разбивается от первого удара. Общий базовый класс заставил бы их принадлежать к одному семейству. Интерфейс называет то единственное, что их объединяет, а каждый скрипт реализует его по-своему:
public interface IDamageable
{
void TakeDamage(int amount);
}public class PlayerHealth : MonoBehaviour, IDamageable
{
public int hp = 10;
public void TakeDamage(int amount)
{
hp -= amount;
Debug.Log("Ouch! hp: " + hp);
}
}public class Crate : MonoBehaviour, IDamageable
{
public void TakeDamage(int amount)
{
Destroy(gameObject);
}
}У скрипта по-прежнему один базовый класс — MonoBehaviour, а интерфейсы перечисляются после него. Интерфейс размещается в отдельном файле IDamageable.cs и не наследуется от MonoBehaviour: это не компонент, и сам по себе он никогда не добавляется к объекту. В классе, где он указан, должен быть публичный метод TakeDamage(int), иначе класс не скомпилируется.
Объект, наносящий урон, запрашивает интерфейс, а не класс:
// Fireball.cs
void OnCollisionEnter(Collision collision)
{
IDamageable target = collision.gameObject.GetComponent<IDamageable>();
if (target != null)
{
target.TakeDamage(3);
}
Destroy(gameObject);
}Огненный шар наносит урон игроку и разбивает ящики с помощью одних и тех же строк кода, а если позже добавится новый тип цели, здесь ничего менять не потребуется. Unity не отображает в Inspector поле типа интерфейса, поэтому скрипты хранят GameObject или компонент и запрашивают у него интерфейс, как это делает огненный шар.
Задание
ЛегкоСделай так, чтобы снеговик, колокол и пугало реализовывали IDamageable, чтобы молот попадал по ним.
Snowman:TakeDamageуменьшает его размер на0.25f * amountпо каждой оси; если размер становится равным 0.5 или меньше, уничтожь его.Bell: выводи в журналDongза каждую единицу и добавляйamountкrings.Scarecrow: только при первом ударе вызываетсяtransform.Rotate(0f, 0f, 90f);.- В
SlamвызывайTakeDamage(power)дляIDamageableкаждого коллайдера, если он есть.
Нажми «Играть» и ударь по каждому объекту. Затем нажми «Проверить».
Попробуйте сами
using UnityEngine;
public class Snowman : MonoBehaviour
{
}
Все уроки раздела Архитектура игр в Unity
1Компоненты, а не иерархии
Небольшие компонентыБазовый скрипт врагаАбстрактные компонентыКомпоненты работают вместеПовторение: модульная турельПовторение: спаренная пушка4Сериализованные данные
Сериализуемые классыСписки в инспектореПеречисления в инспектореПовторение: таблица добычиПовторение: определяем добычу2Интерфейсы в Unity
IDamageableИнтерфейсы и TryGetComponentGetComponentsПовторение: клавиша взаимодействияПовторение: ближайший в пределах досягаемости5ScriptableObjects
Ресурсы данныхХарактеристики оружияОбщие настройкиСохраняем ветерВолны как данныеПовторение: база предметовПовторение: покупка в магазинеПотренируйтесь самостоятельно: Песочница Unity