简体   繁体   中英

Unity: Custom Inspector for ScriptableObject not working

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.

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();
    }
}

It is considered best practice to cache your casted 'target' on the OnEnable method of the inspector. You also have a typo, you're setting dirty an object variable called 'bc' while your target variable is 'obj', you also are setting it dirty every draw call, this will keep dirtying your project all the time, preferably dirty it when something actually changed.

[CustomEditor(typeof(ScriptableObjects.OBJ))]
public class OBJEditor: UnityEditor.Editor 
{
    ScriptableObjects.OBJ obj = null;
    protected void OnEnable()
    {
        obj = (ScriptableObjects.OBJ)target;
    }
    public override void OnInspectorGUI() 
    {
        serializedObject.Update();

        _ = DrawDefaultInspector();

        EditorGUI.BeginChangeCheck();
        obj.Offset = EditorGUILayout.Vector2Field("Offset", obj.Offset);

        ...
        bool somethingChanged = EditorGUI.EndChangeCheck();
        if(somethingChanged)
        {
            EditorUtility.SetDirty(obj);
        }
        serializedObject.ApplyModifiedProperties();
    }
}

You need to pass the correct object to mark as dirty to EditorUtility.SetDirty(); . Currently you're passing bc but you need to pass obj , because thats how you named it in your code. This will mark your ScriptableObject as dirty and once you select File > Save Project , it will be saved.

So change EditorUtility.SetDirty(bc); to EditorUtility.SetDirty(obj);

I had the same issue and it required me adding the keyword

[CanEditMultipleObjects]

to the top of the class definition.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM