Как редактировать пары ключ-значение (например, словарь) в инспекторе Unity?

18

У меня есть система заклинаний, которую я создаю, принцип таков:

  • Каждое заклинание является автономным префабом. Он содержит скрипт с некоторыми свойствами (базовый урон, длительность ...), которые можно изменить в инспекторе.
  • У меня есть перечисление Spell, перечисляющее все возможные заклинания в коде, который используется в игровой логике
  • Когда я хочу разыграть заклинание, мне нужно иметь возможность получить префаб этого заклинания, чтобы создать его экземпляр и прочитать информацию о нем.
  • Каждый актер (будь то игрок или враг) должен иметь список возможных анимаций для заклинаний

Проблемы с тем, как я пытаюсь реализовать:

  • Для отображения анимации каждого актера я мог бы использовать a Dictionary<Spell, Animation>, но словари не поддерживаются инспектором, что затрудняет редактирование нескольких типов актеров.
  • Мне нужен какой-то способ, чтобы легко получить доступ к префабу заклинания из соответствующего перечисления. Здесь также я мог бы использовать словарь, но я могу ссылаться только на префабы в инспекторе, а не в коде, то есть я не смог бы заполнить этот словарь

Я ищу способ легко связать перечисления моих заклинаний с соответствующими префабами и анимациями.

Malharhak
источник
1
Могу ли я предложить изменить заголовок этого вопроса, чтобы он ссылался на поведение словаря (отображение пар ключ-значение) в инспекторе Unity? Это поможет упростить поиск вопроса для других пользователей, которые имеют или ищут идеи для решения такого рода проблем. Несмотря на то, что этот конкретный случай касается заклинаний, те же методы более широко применимы.
DMGregory
@DM Я не знаю Unity, но ваши общие рассуждения звучат разумно. Быть смелым и редактировать; откаты дешевы.
Anko

Ответы:

24

Один из быстрых способов получить пары ключ-значение в инспекторе Unity - определить сериализуемый класс записей, а затем использовать их массив или List <>. например...

public class SpellAnimationMap : ScriptableObject
{
   [System.Serializable]
   public class SpellAnimationEntry
   {
       public Spell spell;
       public AnimationClip animation;
   }

   public SpellAnimationEntry[] spellAnimations;    
}

Автоматически, это даст вам изменяемый размер списка в инспекторе, где вы можете ввести ключ и значение, без необходимости написания специального инспектора.

Результат выглядит так:

автоматически сгенерированный инспектор

(Один прием: если в сериализованном классе записей есть поле «Имя», эта строка будет отображаться вместо полных заголовков «Элемент 0». Это полезно, если у вас есть более сложные данные, которые вы хотите эффективно перемещать.)

Создание этого объекта ScriptableObject позволяет вам рассматривать его как актив, совместно используемый типами / экземплярами сущностей, которым необходим одинаковый набор анимации, избегая дублирования списка для каждого. (Другие классы, как правило, сериализуются для каждого экземпляра в Unity). Чтобы пойти по этому пути, вам нужно добавить небольшой скрипт-редактор, который позволит вам создавать их экземпляры в папке «Ресурсы» .


Изменить: теперь это еще проще - вы можете просто добавить этот атрибут над ScriptableObject:

[CreateAssetMenu(fileName = "fileName.asset", menuName = "Some Folder/Menu Label")]

Это помещает ScriptableObject в меню «Создать», например: Снимок экрана, показывающий настроенное меню «Создать» в Unity


При желании можно сделать массив частным и сериализованным, чтобы он по-прежнему отображался в инспекторе, но добавить общедоступный словарь (или частный словарь с общедоступным методом GetAnimation (Spell spell)), который клиенты будут использовать для более эффективного поиска. В своем методе OnEnable () SpellAnimationMap может перебирать свой массив, заполненный инспекторами, для создания этого словаря, снова разделяя преимущества между всеми клиентскими экземплярами. (Обратите внимание, что OnEnable () также вызывается в редакторе при первом создании ресурса, поэтому убедитесь, что ваш массив не равен NULL, прежде чем пытаться его прочитать)

Наконец, вы можете добавить столько данных в этот тип ввода, сколько вам нужно. Например, он может включать в себя также префаб или любое количество других битов данных, которые вы хотите связать с клавишей заклинания.

Можно также написать пользовательских инспекторов для непосредственного заполнения полей Dictionary <,>, но у меня сложилось впечатление, что работать бесперебойно.

Д.М.Григорий
источник
Именно это я и сделал, ожидая ответа, поэтому я приму этот
ответ
0

Прочитайте объяснение, предоставленное @DMGregory

Для тех, кто любит примеры:

public class SpellHandler : ScriptableObject
{
    public Spell[] keys;
    public Animation[] values;

    private Dictionary<Spell, Animation> dic;

    void Awake()
    {
        int length = keys.Length;
        this.dic= new Dictionary<Spell, Animation>(length);
        for (int i = 0; i < length; i++)
        {
            this.dic.Add(keys[i], values[i]);
        } 
    }    
}
Гаян Виракутти
источник