Comment modifier des paires clé-valeur (comme un dictionnaire) dans l'inspecteur Unity?

18

J'ai un système de sorts que je crée, le principe est le suivant:

  • Chaque sort est un préfabriqué autonome. Il contient un script avec quelques propriétés (dégâts de base, durée ...) qui peuvent être modifiées dans l'inspecteur.
  • J'ai une énumération des sorts répertoriant tous les sorts possibles dans le code, qui est utilisé dans la logique du jeu
  • Quand je veux lancer un sort, je dois pouvoir obtenir le préfabriqué de ce sort pour l'instancier et lire ses informations
  • Chaque acteur (qu'il s'agisse de joueurs ou d'ennemis) doit avoir une liste d'animations possibles pour les sorts

Les problèmes avec la façon dont j'essaie de mettre en œuvre sont:

  • Pour répertorier les animations de chaque acteur, je pourrais utiliser un Dictionary<Spell, Animation>, mais les dictionnaires ne sont pas pris en charge par l'inspecteur, ce qui rend difficile la modification facile du type de plusieurs acteurs.
  • J'ai besoin d'un moyen d'accéder facilement à un préfabriqué de sorts à partir de l'énumération correspondante. Ici aussi, je pourrais utiliser un dictionnaire mais je ne peux faire référence qu'aux préfabriqués dans l'inspecteur, pas dans le code, ce qui signifie que je ne serais pas en mesure de remplir ce dictionnaire

Je cherche un moyen d'associer facilement mes énumérations de sorts aux préfabriqués et animations correspondants

Malharhak
la source
1
Puis-je suggérer de changer le titre de cette question pour faire référence à l'obtention d'un comportement de type dictionnaire (mappage de paires clé-valeur) dans l'inspecteur Unity? Cela aidera à rendre la question plus facile à trouver pour les autres utilisateurs qui ont, ou recherchent, des idées pour résoudre ce type de problème. Même si ce cas spécifique concerne les sorts, les mêmes techniques sont plus largement applicables.
DMGregory
@DM Je ne connais pas Unity, mais votre raisonnement général semble raisonnable. Soyez audacieux et éditez; les retours en arrière sont bon marché.
Anko

Réponses:

24

Un moyen rapide d'obtenir des paires clé-valeur dans l'inspecteur Unity consiste à définir une classe d'entrée sérialisable, puis à utiliser un tableau ou une liste <> d'entre elles. par exemple...

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

   public SpellAnimationEntry[] spellAnimations;    
}

Automatiquement, cela vous donnera une liste redimensionnable dans l'inspecteur où vous pourrez entrer la clé et la valeur, sans avoir besoin d'écrire un inspecteur personnalisé.

Le résultat ressemble à ceci:

inspecteur généré automatiquement

(Une astuce: si la classe d'entrée sérialisée contient un champ "Nom", cette chaîne sera affichée à la place des en-têtes fades "Élément 0". Utile si vous avez des données plus complexes que vous souhaitez pouvoir naviguer efficacement.)

En faire un ScriptableObject vous permet de le traiter comme un actif partagé entre des types d'entités / instances qui ont besoin du même jeu d'animation, évitant ainsi la surcharge de duplication de la liste pour chacun. (Les autres classes ont tendance à être sérialisées par instance dans Unity). Pour suivre cette voie, vous devrez ajouter un petit script d'éditeur pour vous permettre de créer des instances de ceux-ci dans votre dossier Assets .


Edit: maintenant c'est encore plus facile - vous pouvez simplement ajouter cet attribut au-dessus de votre ScriptableObject:

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

Cela place le ScriptableObject dans votre menu Créer, comme ceci: Capture d'écran montrant un menu Créer personnalisé dans Unity


Vous pouvez éventuellement rendre le tableau privé et sérialisé afin qu'il s'affiche toujours dans l'inspecteur, mais ajouter un dictionnaire public (ou un dictionnaire privé avec une méthode publique GetAnimation (sort orthographique)) pour que les clients les utilisent pour des recherches plus efficaces. Dans sa méthode OnEnable (), le SpellAnimationMap peut parcourir son tableau rempli par l'inspecteur pour créer ce dictionnaire une fois, partageant à nouveau l'avantage entre toutes les instances clientes. (Notez que OnEnable () est également appelé dans l'éditeur lors de la création de l'actif, assurez-vous donc de vérifier que votre tableau n'est pas nul avant d'essayer de le lire)

Enfin, vous pouvez en ajouter autant que vous le souhaitez dans ce type de données d'entrée. Il peut également inclure le préfabriqué, par exemple, ou n'importe quel nombre d'autres bits de données que vous souhaitez lier à la clé de sort.

Il est également possible d'écrire des inspecteurs personnalisés pour remplir directement les champs Dictionnaire <,>, mais l'impression que j'ai est qu'il est difficile de travailler correctement.

DMGregory
la source
Exactement ce que je faisais en attendant une réponse, donc, j'accepterai celle-ci
Malharhak
0

Lisez l'explication fournie par @DMGregory

À ceux qui aiment les exemples:

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
la source