Unity: Custom Inspector for ScriptableObject not working

Timisorean picture Timisorean · Sep 15, 2019 · Viewed 7.4k times · Source

I created a custom Inspector for some of my ScriptableObject. The inspector seems to work perfectly. If a value gets changed in the inspector, this value is used in game. But as soon as I restart Unity the value is back on its old value, so the changed are not applied to the file. I have checked that by looking in the file. Here is my custom Inspector:

[CustomEditor(typeof(ScriptableObjects.OBJ))]
public class OBJEditor: UnityEditor.Editor {
    public override void OnInspectorGUI() {
        _ = DrawDefaultInspector();

        ScriptableObjects.OBJ obj = (ScriptableObjects.OBJ) target;
        obj.Offset = EditorGUILayout.Vector2Field("Offset", obj.Offset);

        ...

        EditorUtility.SetDirty(obj);
    }
}

I have added the line EditorUtility.SetDirty(bc); because I have read that this line should apply changes to the file. The ... stand for some other lines that are pretty much the same as the two lines above the dots.

How can I save my changes to the ScriptableObject file.

Answer

derHugo picture derHugo · Sep 15, 2019

Do not directly change values through the target at all!

The manually handling of setting dirty and Undo/Redo is complex and unnecessary!

Allways use the built-in serializedObject and go through SerializedProperty

[CustomEditor(typeof(ScriptableObjects.OBJ))]
public class OBJEditor: UnityEditor.Editor 
{
    private SerializedProperty offset;

    private void OnEnable()
    {
        // Link the properties
        offset = serializedObject.FindProperty("Offset");
    }

    public override void OnInspectorGUI() 
    {
        DrawDefaultInspector();

        // Load the real class values into the serialized copy
        serializedObject.Update();

        // Automatically uses the according PropertyDrawer for the type
        EditorGUILayout.PropertyField(offset);

        ...

        // Write back changed values and evtl mark as dirty and handle undo/redo
        serializedObject.ApplyModifiedProperties();
    }
}