Jak edytować pary klucz-wartość (np. Słownik) w inspektorze Unity?

18

Mam system czarów, który tworzę, zasada jest następująca:

  • Każde zaklęcie jest autonomicznym prefabrykatem. Zawiera skrypt z niektórymi właściwościami (obrażenia podstawowe, czas trwania ...), które można modyfikować w inspektorze.
  • Mam wyliczenie zaklęcia z listą wszystkich możliwych zaklęć w kodzie, które są używane w logice gry
  • Kiedy chcę rzucić zaklęcie, muszę mieć prefabrykację tego zaklęcia, aby utworzyć jego instancję i przeczytać jej informacje
  • Każdy aktor (gracze lub wrogowie) musi mieć listę możliwych animacji zaklęć

Problemy z tym, jak próbuję wdrożyć, to:

  • Aby wyświetlić listę animacji każdego aktora, mógłbym użyć Dictionary<Spell, Animation>, ale inspektor nie obsługuje słowników, co utrudnia łatwą edycję typu wielu aktorów.
  • Potrzebuję sposobu, aby łatwo uzyskać dostęp do prefabrykacji zaklęcia z odpowiedniego wyliczenia. Tutaj także mogę użyć słownika, ale mogę odwoływać się tylko do prefabrykatów w inspektorze, a nie do kodu, co oznacza, że ​​nie będę w stanie wypełnić tego słownika

Szukam sposobu, aby łatwo powiązać moje wyliczenia zaklęć z odpowiednimi prefabrykatami i animacjami

Malharhak
źródło
1
Czy mogę zasugerować zmianę tytułu tego pytania, aby odnosiło się do uzyskiwania zachowań przypominających słownik (mapowanie par klucz-wartość) w inspektorze Unity? Pomoże to w znalezieniu pytania innym użytkownikom, którzy mają lub szukają pomysłów na rozwiązanie tego rodzaju problemu. Chociaż ten konkretny przypadek dotyczy zaklęć, te same techniki mają szersze zastosowanie.
DMGregory
@DM Nie znam Unity, ale twoje ogólne rozumowanie brzmi rozsądnie. Bądź odważny i edytuj; wycofywanie jest tanie.
Anko

Odpowiedzi:

24

Jednym szybkim sposobem na uzyskanie par klucz-wartość w inspektorze Unity jest zdefiniowanie możliwej do serializacji klasy wejściowej, a następnie użycie ich tablicy lub listy <>. na przykład...

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

   public SpellAnimationEntry[] spellAnimations;    
}

Automatycznie da to listę kontrolera, której rozmiar można zmienić, w której można wprowadzić klucz i wartość, bez konieczności pisania niestandardowego inspektora.

Wynik wygląda następująco:

automatycznie generowany inspektor

(Jedna sztuczka: jeśli serializowana klasa wejściowa zawiera pole „Nazwa”, ten ciąg zostanie wyświetlony zamiast nijakich nagłówków „Element 0”. Przydatne, jeśli masz bardziej złożone dane, aby móc efektywnie nawigować.)

Uczynienie tego ScriptableObject pozwala traktować go jako Zasób współdzielony między typami encji / instancjami, które wymagają tego samego zestawu animacji, unikając narzucania się duplikacji listy dla każdego z nich. (Inne klasy są zazwyczaj serializowane na instancję w Unity). Aby przejść tę trasę, musisz dodać mały skrypt edytora, aby umożliwić tworzenie ich instancji w folderze Zasoby .


Edycja: teraz jest jeszcze łatwiej - możesz po prostu dodać ten atrybut nad ScriptableObject:

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

Spowoduje to umieszczenie obiektu ScriptableObject w menu Utwórz, na przykład: Zrzut ekranu przedstawiający dostosowane menu Utwórz w Unity


Opcjonalnie możesz ustawić tablicę jako prywatną i zserializowaną, aby nadal wyświetlała się w inspektorze, ale dodać publiczny Słownik (lub słownik prywatny z publiczną metodą GetAnimation (pisownia)), aby klienci mogli z niego korzystać w celu bardziej wydajnego wyszukiwania. W metodzie OnEnable () SpellAnimationMap może iterować przez tablicę wypełnioną inspektorem, aby zbudować ten słownik ponownie, ponownie dzieląc korzyści między wszystkimi instancjami klienta. (Zauważ, że OnEnable () jest także wywoływany w edytorze, gdy zasób jest tworzony po raz pierwszy, więc upewnij się, że tablica nie ma wartości null, zanim spróbujesz go odczytać)

Na koniec możesz dodać tyle danych wejściowych, ile potrzebujesz. Może na przykład obejmować prefabrykaty lub dowolną liczbę innych bitów danych, które chcesz połączyć z kluczem pisowni.

Możliwe jest również pisanie niestandardowych inspektorów, aby bezpośrednio wypełniać pola Dictionary <,>, ale mam wrażenie, że dziwnie jest pracować płynnie.

DMGregory
źródło
Dokładnie to, co zrobiłem, czekając na odpowiedź, więc zaakceptuję tę
Malharhak
0

Przeczytaj wyjaśnienie dostarczone przez @DMGregory

Dla tych, którzy lubią przykłady:

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]);
        } 
    }    
}
Gayan Weerakutti
źródło