EditorWindow member serialization in OnDisable

So I’ve recently run into an issue with transitioning an EditorWindow instance from editor mode to play mode. I want to set a serializable member to a value so that when play mode button is pressed (which reloads the Mono DLLs), the value of the member is set back to what it was in editor mode. I’ve read this blog post, which explained quite a bit about how it’s done, and how to overcome some standard cases.

The problem is that I need to set the member at the end of the EditorWindow’s edit mode lifespan, and as far as I’m aware, that means it has to be done in OnDisable(). However, it seems that the editor-to-play serialization happens sometime before OnDisable(), so any changes made to the member in that function aren’t a part of serialization.

Here is the scenario at its simplest:

using UnityEditor;
using UnityEngine;

public class ExampleWindow : EditorWindow
{
    static ExampleWindow()
    {
        // prints out whatever libraries are reloaded
        System.AppDomain.CurrentDomain.AssemblyLoad += 
            (object sender, System.AssemblyLoadEventArgs args) =>
            {
                Debug.Log("Assembly loaded: " + args.LoadedAssembly.FullName);
            };
    }

    [MenuItem("MenuItem/Example")]
    public static void Init()
    {
        GetWindow(typeof(ExampleWindow));
    }

    void OnEnable()
    {
        Debug.Log("OnEnable: " + x);
        x = 66;
    }
    void OnDisable()
    {
        Debug.Log("OnDisable");
        x = 42;
    }

    [SerializeField]
    int x;
}

When the window is first created, OnEnable is called - x is logged as 0, then x gets set to 66. If play mode is entered while this instance is still open, OnDisable gets called - x is set to 42. The assemblies are then reloaded for play mode, so OnEnable gets called again - but instead of logging 42, x is 66. This is what leads me to believe that serialization has happened prior to OnDisable.

I was curious what you all had to make of this, and what I could do to get it working appropriately. Is there a function I’m not aware of that I could use to get this member set near the end of a lifespan but before serialization? If not, any other solutions? I’d like to avoid something redundant like setting in Update().

I haven’t encountered your specific issue, but I’ve been coding around the thought that the flow is:

{User clicks Play}, then OnDisable, then OnEnable

I may be wrong; have you tried Debug.Logs to be sure your OnEnable write isn’t overwriting your OnDisable?

Perhaps OnLostFocus and OnDestroy might fit your model better?

I hope by redundant you mean setting the values every frame, because mine involves a flag check in OnGUI in your EditorWindow…

If you just need different value for runtime and editor mode, then a simple hack could work:

	void OnGUI(){
		if(Application.isPlaying != modeFlag){
			modeFlag = Application.isPlaying;
			if(modeFlag)
				x = 42;
			else
				x = 66;
		}
		GUILayout.Label(x.ToString());
		Repaint();
	}

This would skip serialization completely.