Cuando trabajas con scriptable objects en Unity y tu base de datos de ítems crece, el inspector por defecto puede volverse confuso. Campos que no corresponden a ciertos tipos de ítems aparecen visibles, y la experiencia de edición se degrada. La solución está en construir un custom editor que controle exactamente qué se muestra y cómo se muestra en el inspector.
¿Cómo se estructura un custom editor en Unity?
Antes de escribir código, es fundamental organizar el proyecto. Todo lo relacionado con la visualización del editor debe vivir dentro de una carpeta llamada editor [0:44]. Esto garantiza que Unity no incluya ese código en el build final del juego.
Para crear el editor personalizado, se genera una nueva clase. En este caso se llama ItemScriptableEditor. Lo primero es importar la librería correspondiente:
- Se agrega
using UnityEditor para acceder a las herramientas de edición.
- La clase no hereda de MonoBehaviour, sino de
Editor [1:18].
- Se utiliza el atributo
[CustomEditor(typeof(ItemScriptableObject))] para indicar a qué tipo de scriptable object aplica este editor [1:30].
Con esto, Unity ya sabe que cuando selecciones un scriptable object de tipo ítem, debe usar tu editor personalizado en lugar del inspector genérico.
¿Qué hace el método OnInspectorGUI?
El método OnInspectorGUI es el equivalente a un update pero para el inspector [1:55]. Se ejecuta cada vez que el inspector está enfocado en el objeto. Si dentro de este método llamas a base.OnInspectorGUI(), dibuja el inspector por defecto. Si lo dejas vacío, el inspector queda completamente en blanco, aunque los datos siguen almacenados internamente [2:15].
¿Por qué usar OnEnable para buscar propiedades?
Como OnInspectorGUI se ejecuta repetidamente, buscar propiedades dentro de él puede generar problemas de rendimiento con bases de datos grandes [2:48]. La estrategia recomendada es usar OnEnable, que se ejecuta una sola vez cuando el objeto se abre.
¿Cómo se obtienen las serialized properties?
El concepto de SerializedProperty es clave para trabajar con editores personalizados [3:15]. Cada campo del scriptable object se representa como una propiedad serializada que puedes buscar y manipular.
Los pasos son:
- Declarar variables de tipo
SerializedProperty para cada campo: nombre, tipo de ítem, ícono, restore amount y daño.
- Obtener el
serializedObject, que representa la clase completa del scriptable object [3:38].
- Buscar la propiedad raíz con
FindProperty("item"), usando el nombre exacto del campo en el script original [3:52].
- Para propiedades anidadas, usar
FindPropertyRelative() desde la propiedad padre [4:36].
csharp
SerializedProperty itemProp, nameProp, iconProp, restoreProp, damageProp;
void OnEnable()
{
var SO = serializedObject;
itemProp = SO.FindProperty("item");
nameProp = itemProp.FindPropertyRelative("displayName");
iconProp = itemProp.FindPropertyRelative("icon");
restoreProp = itemProp.FindPropertyRelative("restoreAmount");
damageProp = itemProp.FindPropertyRelative("damage");
}
Un detalle crítico: los nombres de las propiedades deben coincidir exactamente con los del script original, respetando mayúsculas y minúsculas [4:00]. Si cambias un nombre en el scriptable object, debes actualizarlo también en el editor.
¿Cómo depurar un custom editor con breakpoints?
Para verificar que las propiedades se están encontrando correctamente, se puede usar el método de breakpoints directamente en el IDE [5:10]. Se coloca un punto de interrupción en OnEnable, se conecta el depurador a Unity y se inspecciona cada variable.
En este caso, al depurar se encontraron dos errores comunes:
- Un campo llamado
item dentro de una clase que también se llamaba item, lo que generaba confusión. Se renombró a typeItem usando el atajo Ctrl+R, R para refactorizar de forma segura [5:45].
- El campo
displayName tenía una discrepancia de mayúsculas entre el script y la búsqueda en el editor [6:00].
Corregidos estos detalles, todas las serialized properties se cargaron correctamente y el editor quedó listo para la siguiente fase: dibujar los campos de forma personalizada en el inspector.