Решили: enum-поля ассетов, создаваемых кодом, ставятся по имени — поиском в
SerializedProperty.enumNames, — а не присваиванием числа в enumValueIndex.
Почему: enumValueIndex — это позиция в списке имён, и со значением enum она совпадает только у
перечислений без дыр в номерах. Совпадение это встречается часто, поэтому ошибка не воспроизводится в
простых случаях и выглядит как «всё работает».
Грабли: пять ассетов кита мага ветра были заведены с чужими значениями, и ничто этого не поймало — ни компилятор, ни 117 тестов контента: поля валидны, просто держат не то.
DamageTypeидёт 1, 2, 3, … 10, 11, 12, 13, 22.enumValueIndex = 13, которым ставилась «Аркана», записалоPure— урон, не гасимый ни бронёй, ни резистами, на автоатаке поддержки.EffectPolarityобъявленBuff, Debuff, Neutral. То есть 0 — это Buff, а не «нейтральный», как подсказывает интуиция. Два бафа легли дебафами: свои снимали бы их клинсом с себя, чужой диспел не трогал бы вовсе. Нейтральные, наоборот, стали бафами.StackRule—None, Stack, Refresh, StackAndRefresh, Portions: индекс 1 далStackвместоStackAndRefresh, то есть стаки копились, но срок не обновлялся.
Как поймалось: движок в ответе напечатал ПРЕЖНЕЕ значение — «Pure → Blunt» вместо ожидаемого «Arcane → Blunt». Это единственное место, где подмена была видна, и увидеть её можно было только читая отчёт инструмента, а не свой код.
Как делать:
for (int i = 0; i < p.enumNames.Length; i++)
if (p.enumNames[i] == "Buff") { p.enumValueIndex = i; break; }Либо распечатать весь enumNames перед правкой и взять номер оттуда. Проверять результат — чтением
свойства объекта (relic.AutoAttackDamageType), а не по коду, который его ставил.
Владелец правды: ассеты Assets/_Project/ScriptableObjects/{Relics,Effects}/, память
serialized-fields-gotchas.