It’s been a while since I’ve last created a CustomEditor, and I seem to have forgotten all about it.
I followed the docs (Unity - Manual: Custom Editors (unity3d.com)), but I instantly get a NullReferenceException on EditorGUILayout.PropertyField(serializedProperty);
here’s the full code:
using UnityEditor;
using UnityEngine;
[CustomEditor(typeof(Trainer))]
public class TrainerEditor : Editor
{
SerializedProperty serializedProperty;
void OnEnable()
{
serializedProperty = serializedObject.FindProperty("Trainer");
}
public override void OnInspectorGUI()
{
serializedObject.Update();
EditorGUILayout.PropertyField(serializedProperty);
serializedObject.ApplyModifiedProperties();
}
}
This is exactly what the docs say, so I have no idea what could possibly be wrong.
Edit:
It seems OnEnable() isn’t being called, because my script was already placed on a gameobject in the scene, so I added
if (serializedProperty==null)
{
serializedProperty = serializedObject.FindProperty("Trainer");
}
before EditorGUILayout.PropertyField(serializedProperty), but serializedProperty remains null, as if it can’t find the Trainer-script?
I was already confused that the method was called FindProperty when I thought we were looking for the class, but I noticed in the docs it’s not the class it’s referncing, but its property with the same name (which is a terrible example from Unity).
Yes, examples are often terrible, a bit misleading or show a complete unrealistic usecase. Please if you find such an example, the documentation has a voting / reporting system at the bottom. So just report it as a problem and maybe suggest a change (like calling the property “target” instead).
The example isn’t great but I do find it odd that you thought the FindProperty argument was anything other than the property you actually wanted to find i.e. thinking it was the encapsulating class type. It’d have no way to know which property you actually wanted. The example whilst far from optimal does show specifying the property required and not the class.
With all that aside, I do completely agree with @Bunny83 above.
I’ll be honest, Unity is that big that even I search the codebase to remind myself of things I don’t touch often and I’ve worked here for over 11 years.
The reason I thought that was because I did remember having to do something like var trainer = target as Trainer; to be able to access the properties, and I mistakenly thought serializedProperty = serializedObject.FindProperty("Trainer"); was this code.
Note that there are two ways to access the edited object(s)
Access target / targets directly
Use the SerializedObject / SerializedProperty system.
The Editor class provides you with both solutions. Though you actually don’t “need” to use the serializedObject that is already provided by the Editor class and you “could” use your own. Though that wouldn’t make much sense. However it might help to better understand the relationship. The target / targets properties reference the actual object(s) that is / are eedited. You could create a SerializedObject from the targets array.
public override void OnInspectorGUI()
{
SerializedObject so = new SerializedObject(targets);
so.Update();
EditorGUILayout.PropertyField(so.FindProperty("someField"));
so.ApplyModifiedProperties();
}
The SerializedObject is actually a wrapper that abstracts the serialized data of one or multiple objects into a single object. When Update is called on the SerializedObject, the serialized data is actually loaded from disk into the internal structure (SerializedProperties). You then edit those SerializedProperties and when you call ApplyModifiedProperties, the changed data is written back to the actual objects / serialized data.
SerializedObject is the “new” way to edit objects as they allow multi object editing out of the box and handle undo and “dirtying” automatically. Of course since the Editor already provides the initialized “serializedObject”, there’s no need to create one yourself.