¿Cómo editar pares clave-valor (como un diccionario) en el inspector de Unity?

18

Tengo un sistema de hechizos que estoy creando, el principio es el siguiente:

  • Cada hechizo es un prefabricado autónomo. Contiene un script con algunas propiedades (daño base, duración ...) que se pueden modificar en el inspector.
  • Tengo una enumeración de hechizos que enumera todos los hechizos posibles en el código, que se usa en la lógica del juego
  • Cuando quiero lanzar un hechizo, necesito poder obtener el prefabricado de este hechizo para instanciarlo y leer su información
  • Cada actor (ya sean jugadores o enemigos) necesita tener una lista de posibles animaciones para los hechizos.

Los problemas con la forma en que estoy tratando de implementar son:

  • Para enumerar las animaciones de cada actor, podría usar un Dictionary<Spell, Animation>, pero el inspector no admite los diccionarios, lo que dificulta editar fácilmente el tipo de múltiples actores.
  • Necesito alguna forma de acceder fácilmente a un hechizo prefabricado desde la enumeración correspondiente. Aquí también podría usar un diccionario, pero solo puedo hacer referencia a prefabricados en el inspector, no en el código, lo que significa que no podría llenar este diccionario

Estoy buscando una manera de asociar fácilmente mis enumeraciones de hechizos a las prefabricaciones y animaciones correspondientes

Malharhak
fuente
1
¿Puedo sugerir cambiar el título de esta pregunta para referirse a obtener un comportamiento similar al de un diccionario (asignación de pares clave-valor) en el inspector de Unity? Esto ayudará a que la pregunta sea más fácil de encontrar para otros usuarios que tienen o están buscando ideas para resolver este tipo de problema. Aunque este caso específico se trata de hechizos, las mismas técnicas son más ampliamente aplicables.
DMGregory
@DM No conozco Unity, pero tu razonamiento general suena sensato. Sé audaz y edita; los retrocesos son baratos.
Anko

Respuestas:

24

Una forma rápida de obtener pares clave-valor en el inspector de Unity es definir una clase de entrada serializable y luego usar una matriz o Lista <> de ellos. p.ej...

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

   public SpellAnimationEntry[] spellAnimations;    
}

Automáticamente, esto le dará una lista redimensionable en el inspector donde puede ingresar la clave y el valor, sin necesidad de escribir un inspector personalizado.

El resultado se ve así:

inspector autogenerado

(Un truco: si la clase de entrada serializada contiene un campo "Nombre", esa cadena se mostrará en lugar de los encabezados blandos "Elemento 0". Útil si tiene datos más complejos que desea poder navegar de manera eficiente).

Hacer de este un ScriptableObject le permite tratarlo como un Activo compartido entre los tipos / instancias de entidad que necesitan el mismo conjunto de animación, evitando la sobrecarga de duplicar la lista para cada uno. (Otras clases tienden a ser serializadas por instancia en Unity). Para seguir esta ruta, deberá agregar un pequeño script de editor que le permita crear instancias de estos en su carpeta de Activos .


Editar: ahora es aún más fácil: simplemente puede agregar este atributo sobre su ScriptableObject:

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

Esto coloca el ScriptableObject en su menú Crear, así: Captura de pantalla que muestra un menú Crear personalizado en Unity


Opcionalmente, puede hacer que la matriz sea privada y serializada para que todavía aparezca en el inspector, pero agregue un Diccionario público (o un diccionario privado con un método público GetAnimation (Spell Spell)) para que los clientes lo consuman para búsquedas más eficientes. En su método OnEnable (), SpellAnimationMap puede iterar a través de su matriz poblada por el inspector para construir este diccionario una vez, nuevamente compartiendo el beneficio entre todas las instancias del cliente. (Tenga en cuenta que OnEnable () también se llama en el editor cuando se crea el activo por primera vez, así que asegúrese de verificar que su matriz no sea nula antes de intentar leerla)

Finalmente, puede agregar todo lo que necesite a este tipo de datos de entrada. También podría incluir el prefabricado, por ejemplo, o cualquier otro número de bits de datos que desee vincular a la clave ortográfica.

También es posible escribir inspectores personalizados para rellenar los campos Diccionario <,> directamente, pero la impresión que obtengo es que es complicado trabajar sin problemas.

DMGregory
fuente
Exactamente lo que hice mientras esperaba una respuesta, así que aceptaré esta
Malharhak,
0

Lea la explicación proporcionada por @DMGregory

Para aquellos que les gustan los ejemplos:

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
fuente