Menu
CoddyTech

Перечисления в инспекторе

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

Поле перечисления отображается в Inspector в виде раскрывающегося списка — это удобный способ настраивать объекты, использующие один скрипт. Один префаб Pickup подходит для монет, сердец и щитов: каждая его копия на уровне получает свой тип из раскрывающегося списка, а скрипт выбирает действие в зависимости от него:

public enum PickupKind { Coin, Heart, Shield }

public class Pickup : MonoBehaviour
{
    public PickupKind kind;
    public int amount = 1;

    void OnTriggerEnter(Collider other)
    {
        if (!other.TryGetComponent(out PlayerStats stats)) return;
        switch (kind)
        {
            case PickupKind.Coin: stats.coins += amount; break;
            case PickupKind.Heart: stats.hp += amount; break;
            case PickupKind.Shield: stats.shielded = true; break;
        }
        Destroy(gameObject);
    }
}

Сцена сохраняет каждый вариант как числовое значение: Coin — это 0, Heart — 1, Shield — 2. Добавить значение в конец безопасно. Если вставить его в начало, как в { Gem, Coin, Heart, Shield }, все числа сдвинутся, и тип каждого Pickup во всех сценах изменится. Переименовать значение безопасно, поскольку его число останется прежним. Если явно указать числа — Coin = 0, Heart = 1, Shield = 2, — позже можно будет менять порядок названий, не затрагивая сохранённые варианты.

Перечисление [System.Flags] хранит несколько значений одновременно. В его раскрывающемся списке для каждого значения есть флажок, а также пункты Nothing и Everything. Каждому значению нужен собственный бит, поэтому используются степени двойки:

[System.Flags]
public enum Element { None = 0, Fire = 1, Ice = 2, Poison = 4 }

public Element immuneTo;   // отмечены в Inspector: Fire и Poison

public void Hit(int damage, Element element)
{
    if (immuneTo.HasFlag(element)) return;
    hp -= damage;
}

| объединяет значения: Element.Fire | Element.Poison равно 5. HasFlag(x) возвращает true, когда установлены все значения из x, а ToString() перечисляет установленные значения, например Fire, Poison.

challenge icon

Задание

Легко

Пусть двери требуют несколько ключ-карт, а кольцо хранит несколько карт.

  1. В KeyRing.cs поставь [System.Flags] над Access и пронумеруй его так: None = 0, Red = 1, Blue = 2, Green = 4.
  2. Add(Access card) сохраняет уже имеющиеся карты: cards |= card;.
  3. Opens(Access needs) возвращает true, только когда кольцо хранит каждую карту из needs.

Нажми «Играть» и подбери обе карты: хранилище откроется. Затем нажми «Проверить».

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

using UnityEngine;

public enum Access { None, Red, Blue, Green }

public class KeyRing : MonoBehaviour
{
    public Access cards;

    public void Add(Access card)
    {
        // добавить карту в связку, сохранив уже имеющиеся карты
    }

    public bool Opens(Access needs)
    {
        // true, если в связке есть все карты из needs
        return false;
    }
}

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

Потренируйтесь самостоятельно: Песочница Unity