Why doesn't my ScriptableObject save using a custom EditorWindow?

Solution

Call EditorUtility.SetDirty(yourObject); on any changes made to it.


I have a problem where a ScriptableObject doesn't save its members properly when edited through a custom EditorWindow. It saves properly when edited through the inspector. I can see through the inspector that the ScriptableObject is affected properly by the EditorWindow.

Am I required to explicitly call some SaveAsset() function on the object when editing it through the EditorWindow? Either that, or it might be some bug in Unity. In the former case, does anyone know how I can save the ScriptableObject? In the latter case, does anyone know of a workaround?

Further, the ScriptableObject contains two ints for width and height, and a one-dimensional array of a custom enum type (basically a flattened 2d array). Both the ScriptableObject and the the custom enum type uses System.Serializable attribute on the class and enum type. All fields are public. No properties are being used. The ScriptableObject also exists in the project, so it is not a transient object.


Currently I am trying to force-save the asset through AssetDatabase.SaveAssets. This approach doesn't seem natural as I don't want to necessarily save all assets, only the one I am editing.

However, as I found out after some trial and error AssetDatabase.SaveAssets doesn't actually save the asset as expected.

You need to call EditorUtility.SetDirty() on your scriptable object.

I tried EditorUtility.SetDirty(...), Undo.RecordObject(...), SerializedObject.Update(), SerializedObject.ApplyModifiedProperties(), none of them have any effect. The only thing that did have effect is AssetDatabase.SaveAssets(), but that causes horrible stutter.

I thouth that maybe Unity only saves modified assets on exit, so I tested that too. It didn’t work.

I know this is answered, but I came across this topic while trying to resolve a similar issue. If you are making edits to non-unity objects, like custom structs, but the change is not reflected you may want to use Repaint().