en Tutoriales, Unity

Simple CustomEditor

Con este tutorial intentaremos explicar como empezar a usar el CustomEditor con la clase List

Un CustomEditor nos permite cambiar la representación visual de nuestras clases en el Unity Inspector. Hace más sencillo interactuar con las script classes asociadas a  Gameobjects, prefabs, etc…

Componente sin CustomEditor

Componente con CustomEditor

Nuestro primer paso es crear una carpeta con el nombre Editor. Para Unity es un nombre de carpeta muy especial, Unity carga automaticamente todos los scripts que modifican el comportamiento del UnityEditor desde esta carpeta. Estos scripts NO serán incluidos en el empaquetado final del juego, solo serán usado por el UnityEditor

Creamos dos carpetas más: Scripts y Scenes para guardar el resto de scripts y la escena que tendrá nuestro trabajo

El árbol de directorios nos queda así:

Assets
|_Editor
|_Scripts
|_Scenes

Empezaremos con dos clases muy simples, primero creamos un nuevo script con el nombre de Data.cs en nuestra carpeta Scripts y añadimos las siguientes clases:

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
 
public class BinarySequence
{
    public int numBits = 5;
    public List<bool> bitList;
}
 
public class Data : MonoBehaviour
{
    public BinarySequence sequence;
}

BinarySequence representará una lista de bits

Queremos clases capaces de ser serializadas. Para hacer esto añadimos la etiqueta [System.Serializable] sobre la declaración de las clases. Ya podemos extraer sus atributos en nuestra clase editor en el siguiente paso.

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
 
 
//The Serializable attribute lets you embed a class with sub properties in the inspector.
[System.Serializable]
public class BinarySequence
{
    public int numBits = 5;
    public List<bool> bitList;
}
 
[System.Serializable]
public class Data : MonoBehaviour
{
    public BinarySequence sequence;
}

Ahora crearemos nuestra clase editor personalizada, creamos un nuevo script en la carpeta Editor llamado DataEditor e importamos la clase editor usada por el UnityEditor.

Añadimos la etiqueta [CustomEditor(typeof(Data))] para indicar que vamos a definir la representacion de la clase Data en el editor. DataEditor hereda de Editor.
Sobreescribimos OnInspectorGUI(), este método será llamado con cada evento del editor

using UnityEngine;
using UnityEditor;
using System.Collections;
 
[CustomEditor(typeof(Data))]
public class DataEditor : Editor
{
    /** Update with each inspector event*/
    public override void OnInspectorGUI ()
    {
        //Insert code here
    }
}

La primera tarea es añadir:

serializedObject.Update();  //update the serializazed object of Data<br>
// Insert code here<br>
serializedObject.ApplyModifiedProperties(); //apply property modifications

Ahora podemos continuar con la interfaz gráfica

Podemos añadir etiquetas de texto usando LabelField

EditorGUILayout.LabelField("Binary sequence");

Extraer los atributos de ‘sequence’ usando el nombre del atributo con el objecto serializado y FindProperty

SerializedProperty sequenceProperty = serializedObject.FindProperty("sequence");

Para extraer los atributos de BinarySequence podemos usar el nombre del atributo con FindPropertyRelative porque usaremos la propiedad extraida previamente.

SerializedProperty bitListProperty = sequenceProperty.FindPropertyRelative("bitList");
SerializedProperty newSizeList = sequenceProperty.FindPropertyRelative("numBits");

Si añadimos el script Data a un objeto la lista será creada con tamaño cero y no podremos ver nada. Para cambiar esto sobreescribimos la propiedad size usando nuestro atributo numBits de BinarySequence.

La variable bitListProperty contiene un objeto serializado de tipo List, por lo tanto, podemos acceder a los atributos de la clase List usando FindPropertyRelative de la misma manera que antes

/** set default size */
bitListProperty.FindPropertyRelative("Array.size").intValue = newSizeList.intValue;
int size = bitListProperty.FindPropertyRelative("Array.size").intValue;

Para dibujar nuestra lista empezamos añadiendo una linea horizontal  y espacios flexibles a cada uno de los lados, así los elementos se mantendrán juntos incluso si se cambia el tamaño del editor.

EditorGUILayout.BeginHorizontal(); 
GUILayout.FlexibleSpace();
//Insert code here
GUILayout.FlexibleSpace();
EditorGUILayout.EndHorizontal();

Nuestro último paso es añadir los elementos de la lista, para hacer esto usaremos un toggle para cada elemento. El valor del toggle debe ser reasignado para guardar el nuevo valor cada vez que pulsamos sobre en el el editor.

EditorGUIUtility.labelWidth = 2;
for (int i = 0; i < size ; ++i)
{
    bitListProperty.GetArrayElementAtIndex(i).boolValue = EditorGUILayout.Toggle(" ",bitListProperty.GetArrayElementAtIndex(i).boolValue);
}

Creamos cinco toggles sin nombre. Por defecto el inspector reserva el espacio para el nombre aunque no lo especifiquemos, para minimizar ese espacio usaremos la propiedad labelWidth con un valor pequeño.

Finalmente el código de DataEditor queda así:

using UnityEngine;
using UnityEditor;
using System.Collections;
 
[CustomEditor(typeof(Data))]
public class DataEditor : Editor
{
    /** Update with each inspector event*/
    public override void OnInspectorGUI ()
    {
     
        serializedObject.Update();
        EditorGUILayout.LabelField("Binary sequence");
        SerializedProperty sequenceProperty = serializedObject.FindProperty("sequence");
         
        SerializedProperty bitListProperty = sequenceProperty.FindPropertyRelative("bitList");
        SerializedProperty newSizeList = sequenceProperty.FindPropertyRelative("numBits");
         
        /** set default size */
        bitListProperty.FindPropertyRelative("Array.size").intValue = newSizeList.intValue;
        int size = bitListProperty.FindPropertyRelative("Array.size").intValue;
         
        EditorGUIUtility.labelWidth = 2;
        EditorGUILayout.BeginHorizontal();
         
        GUILayout.FlexibleSpace();
        for (int i = 0; i < size ; ++i)
        {
            bitListProperty.GetArrayElementAtIndex(i).boolValue = EditorGUILayout.Toggle(" ",bitListProperty.GetArrayElementAtIndex(i).boolValue);
        }
        GUILayout.FlexibleSpace();
        EditorGUILayout.EndHorizontal();
 
        serializedObject.ApplyModifiedProperties();
    }
}

Ahora cada vez que añadimos el script Data a un objeto podremos ver esto en el editor facilitando nuestra interacción con el script:

sequence_selector

Tutorial files

Ayudanos con este blog!

El último año he estado dedicando cada vez más tiempo a la creación de tutoriales, en su mayoria sobre desarrollo de videojuegos. Si crees que estos posts te han ayudado de alguna manera o incluso inspirado, por favor considera ayudarnos a mantener este blog con alguna de estas opciones. Gracias por hacerlo posible!

Escribe un comentario

Comentario