Перейти к основному содержимому

EnumValues

Таблица значений по членам enum, которую заполняют в инспекторе, а не в коде.

Быстрый старт​

До — поля и switchПосле — FastTools
[SerializeField]
private float _default = 1f;
[SerializeField]
private float _fire = 1.5f;

public float GetMultiplier(
DamageType type) => type switch
{
DamageType.Fire => _fire,
_ => _default
};
[SerializeField]
private EnumValues<DamageType, float>
_multipliers;

public float GetMultiplier(
DamageType type) =>
_multipliers.GetValue(type);

GetValue возвращает значение из подходящей строки таблицы, а если такой строки нет — Default Value.

Таблица Multipliers в инспекторе: строка Fire со значением 1.5 и Default Value 1Таблица Multipliers в инспекторе: строка Fire со значением 1.5 и Default Value 1

Заполнение в инспекторе​

Для enum без [Flags] задайте общее значение в Default Value, а отдельные строки добавьте для тех членов, которым нужно другое значение.

Populate Missing Enum Members в контекстном меню заголовка таблицы добавляет строки для недостающих членов enum в конец таблицы и копирует в них Default Value.

Для [Flags] автоматически добавляются только объявленные члены enum. Например, если в enum объявлено FireAndIce = Fire | Ice, команда добавит отдельную строку с ключом FireAndIce. Комбинации без отдельного имени можно добавить вручную.

Populate Missing Enum Members в таблице MultipliersPopulate Missing Enum Members в таблице Multipliers

примечание

Строка, добавленная в пустую таблицу, показывается как <None> и пропускается с ошибкой в Console, пока не выбран член.

Какой вариант выбрать​

Чем отличаютсяEnumValues<TEnum, TValue>EnumValues<TValue>
Где выбирается enumАргумент TEnumЗаголовок таблицы в инспекторе
Ключ в GetValue и foreachTEnumSystem.Enum
Упаковка в GetValueНетКлюч упаковывается
Ключ другого enumНе компилируетсяВозвращает Default Value
  • Значения таблицы задаются в инспекторе; из кода их можно только читать.
  • TValue — любой тип, который сериализует Unity.

В варианте EnumValues<TValue> поле множителей объявляется как EnumValues<float>, а DamageType выбирается в заголовке таблицы:

[SerializeField]
private EnumValues<float>
_multipliers;

DamageType в окне выбора типа в заголовке MultipliersDamageType в окне выбора типа в заголовке Multipliers

  • Выбор enum обязателен: если поле пустое, инспектор показывает Required type is not set. Это поле также учитывает проверка обязательных полей.
  • При первом обращении к таблице с пустым полем enum в Console записывается предупреждение (Warning). Вызовы GetValue возвращают Default Value.

Правила поиска​

Ключ строки — выбранный в ней член enum. Если в таблице несколько строк с одинаковым ключом, используется первая сверху. Члены enum с одинаковым числовым значением тоже считаются одним ключом: например, при объявлении Frost = Ice оба имени обозначают одно значение.

Строки в инспекторе, сверху внизАргумент GetValueВозвращаемое значение
Fire → 0.9
Fire → 0.5
DamageType.Fire0.9
Ice → 0.5DamageType.Frost0.5

Флаги​

[Flags]
public enum DamageType
{
None = 0,
Fire = 1,
Ice = 2,
Frost = Ice,
FireAndIce = Fire | Ice,
Poison = 4
}

[SerializeField]
private EnumValues<DamageType, float>
_multipliers;

Для [Flags] поиск проходит в два этапа:

  1. Сначала ищется точное совпадение: ключ строки содержит тот же набор флагов, что и переданный аргумент.
  2. Если точного совпадения нет, выбирается первая сверху строка, все флаги которой есть в переданном значении.

Пусть Default Value равен 0, а таблица в инспекторе заполнена так:

ПорядокКлючЗначение
1Fire0.9
2Ice0.5
3FireAndIce0.3
4None1

Для этой таблицы вызовы GetValue дадут следующие результаты:

АргументЗначениеПочему
Fire | Ice0.3Точное совпадение с FireAndIce (строка 3): оба флага совпадают
Fire | Ice | Poison0.9В аргументе есть все флаги строк 1, 2 и 3. Точного совпадения нет, поэтому выбрана строка 1
Ice | Poison0.5Подходит Ice (строка 2). Для строк 1 и 3 нужен ещё Fire, которого в аргументе нет
Poison0Подходящих строк нет — Default Value
None1Строка с нулевым ключом подходит только для нулевого аргумента
примечание

Если перенести строку FireAndIce выше Fire, вызов для Fire | Ice | Poison вернёт 0.3. Так порядок строк задаёт приоритет, когда точного совпадения нет.

Строка со значением, равным Default Value, тоже участвует в поиске. Если добавить строку Fire | Poison со значением 0, вызов для этой комбинации вернёт 0 по точному совпадению, вместо 0.9 из строки Fire.

Equals()​

Метод таблицы проверяет, подходит ли ключ к запросу, не читая значений:

var request =
DamageType.Fire | DamageType.Ice;
var key = DamageType.Fire;
_multipliers.Equals(request, key);
ЗапросКлючРезультат
DamageType.Fire | DamageType.IceDamageType.Firetrue
DamageType.FireDamageType.Fire | DamageType.Icefalse
DamageType.Fire | DamageType.IceDamageType.Nonefalse
DamageType.NoneDamageType.Nonetrue

В EnumValues<TValue> метод Equals возвращает false, если тип любого аргумента отличается от enum, выбранного в инспекторе.

Перебор строк​

var total = 0f;
foreach (var entry in _multipliers)
total += entry.Value;

Default Value и строки с неразрешёнными ключами в перебор не входят. После первого обращения, которое инициализирует ключи, прямой foreach по таблице не выделяет память. Перебор через IEnumerable упаковывает перечислитель.

Если enum изменился​

Ключи хранятся по именам членов enum:

ИзменениеРезультат
Члены переставлены или изменены их числовые значенияСтроки остаются привязаны к именам. Изменение алиасов или состава битов флагов может изменить результат поиска
Член переименован или удалёнСтрока показывается как <Missing Ice> и пропускается с ошибкой в Console; вернёте имя — строка снова работает
Enum переименован или перенесён в другой namespace или сборкуEnumValues<TEnum, TValue> работает как раньше; EnumValues<TValue> возвращает Default Value и пишет ошибку, пока enum не выбран заново
В EnumValues<TValue> выбран другой enumКлючи сохраняются: вернёте прежний enum — строки снова работают

Пример в пакете​

Плитки и следы получают цвет из EnumValues<SurfaceType, Color>, а множитель скорости — из EnumValues<float> с выбранным в инспекторе [Flags]-enum: EnumValues.

При переходе на другую поверхность меняются цвет следа и скорость персонажа.При переходе на другую поверхность меняются цвет следа и скорость персонажа.