Como editar pares de valores-chave (como um dicionário) no inspetor do Unity?

18

Eu tenho um sistema de feitiço que estou criando, o princípio é o seguinte:

  • Cada feitiço é uma pré-fabricada autônoma. Ele contém um script com algumas propriedades (dano base, duração ...) que podem ser modificadas no inspetor.
  • Eu tenho um enum Spell listando todas as magias possíveis no código, que é usado na lógica do jogo
  • Quando eu quero lançar um feitiço, eu preciso ser capaz de obter o prefab desse feitiço para instanciar e ler suas informações
  • Cada ator (jogadores ou inimigos) precisa ter uma lista de possíveis animações para os feitiços

Os problemas de como estou tentando implementar são:

  • Para listar as animações de cada ator, eu poderia usar a Dictionary<Spell, Animation>, mas os dicionários não são suportados pelo inspetor, o que dificulta a edição fácil de vários tipos de atores.
  • Eu preciso de alguma maneira de acessar facilmente um prefab de feitiço do enum correspondente. Aqui também eu poderia usar um dicionário, mas só posso fazer referência a prefabs no inspetor, não no código, o que significa que não seria capaz de preencher este dicionário

Estou procurando uma maneira de associar facilmente minhas enumerações de feitiços aos prefabs e animações correspondentes

Malharhak
fonte
11
Posso sugerir que você altere o título desta pergunta para se referir a obter um comportamento semelhante ao dicionário (mapeando pares de valores-chave) no inspetor do Unity? Isso ajudará a tornar a pergunta mais fácil de encontrar para outros usuários que têm ou estão procurando idéias para resolver esse tipo de problema. Embora esse caso específico seja sobre magias, as mesmas técnicas são mais amplamente aplicáveis.
DMGregory
@ DM Eu não conheço o Unity, mas seu raciocínio geral parece sensato. Seja ousado e edite; reversões são baratas.
Anko

Respostas:

24

Uma maneira rápida de obter pares de valores-chave no inspetor do Unity é definir uma classe de entrada serializável e, em seguida, usar uma matriz ou Lista <> delas. por exemplo...

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

   public SpellAnimationEntry[] spellAnimations;    
}

Automaticamente, isso fornecerá uma lista redimensionável no inspetor, onde é possível inserir a chave e o valor, sem a necessidade de escrever um inspetor personalizado.

O resultado fica assim:

inspetor gerado automaticamente

(Um truque: se a classe de entrada serializada contiver um campo "Nome", essa sequência será exibida em vez dos títulos branda "Elemento 0". Útil se você tiver dados mais complexos, poderá navegar com eficiência.)

Tornar isso um ScriptableObject permite tratá-lo como um ativo compartilhado entre tipos / instâncias de entidade que precisam do mesmo conjunto de animações, evitando a sobrecarga de duplicar a lista de cada um. (Outras classes tendem a ser serializadas por instância no Unity). Para seguir esse caminho, você precisará adicionar um pequeno script de editor para criar instâncias desses na sua pasta Assets .


Edit: agora é ainda mais fácil - você pode adicionar este atributo acima do seu ScriptableObject:

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

Isso coloca o ScriptableObject no menu Criar, da seguinte maneira: Captura de tela mostrando um menu Criar personalizado no Unity


Opcionalmente, você pode tornar a matriz privada e serializada para que ela apareça no inspetor, mas adicione um Dicionário público (ou dicionário particular com um método público GetAnimation (Spell)) para os clientes consumirem para pesquisas mais eficientes. No método OnEnable (), o SpellAnimationMap pode percorrer sua matriz preenchida pelo inspetor para criar esse dicionário mais uma vez, compartilhando novamente o benefício entre todas as instâncias do cliente. (Observe que OnEnable () também é chamado no editor quando o ativo é criado pela primeira vez; verifique se sua matriz é não nula antes de tentar lê-la)

Por fim, você pode adicionar esse tipo de dados de entrada conforme necessário. Também pode incluir a pré-fabricada, por exemplo, ou qualquer número de outros bits de dados que você deseja vincular à chave ortográfica.

Também é possível escrever inspetores personalizados para preencher diretamente os campos Dictionary <,>, mas a impressão que eu tenho é que é muito exigente trabalhar sem problemas.

DMGregory
fonte
Exatamente o que aconteceu de eu fazer enquanto espera uma resposta, por isso, eu vou aceitar este
Malharhak
0

Leia a explicação fornecida por @DMGregory

Para quem gosta de exemplos:

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
fonte