programming Unity3D Unity3D-tips

#unity3d missing docs: EditorWindow lifecycle

If you do any non-trivial customization of Unity Editor, you’ll almost certainly extend EditorWindow. But Unity (to date) refuses to tell anyone how to do this legally, or what the contracts you’re being held to are. Without that, many plugins on the Unity Asset Store are wrong and buggy, and sooner or later accidentally cause problems for users.

Their fault? Partly, but I don’t blame them too much – rather: Unity’s fault for failing to document (and failing to test assets before approving them!).

For those of you who aren’t happy shipping crappy, broken, buggy plugins (And charging for them), here’s a guide / reference for the lifecycle of EditorWindow. Extra info, explanations, and gotchas welcome!


6 replies on “#unity3d missing docs: EditorWindow lifecycle”

In my opinion another insidious aspect of the EditorWindow is persistence – if you have an object that is not a MonoBehaviour (but could be a ScriptableObject, in any case it’s not attached to an MB) and you want to manage it via an EditorWindow, then you are entering a world of pain.

You start with something like this (life-cycle handling as described in your post notwithstanding)

On Awake if (myAPI.myDataObect == null) myAPI.myDataObject = new myDataObject.

which is fine except that when you click play the current EditorWindow is serialised and a new “runtime” version of the EditorWindow is instantiated so now you have a new (empty, second, runtime) instance of myDataObject.

obviously when you click stop and enter “edit time” then you end up with a new (empty, edit-time) instance. So you fix this by either making your myObject serialisable, or for a safer approach use a ScriptableObject instead (that’s what they are for right?)

Note this hasn’t fixed the former problem, so when you click play the current EditorWindow is still serialised and a new “runtime” version of the EditorWindow is still instantiated so now you still have a new (empty, second, runtime) instance of myDataObject. However, when you click stop and enter “edit time” then your (first, populated, edit-time) instance is de-serialised but doesn’t contain any run-time changes (intentional behaviour of Unity which seeks to make run-time values tweak-able.) so that’s kindof acceptable.

Now you have an instance of your data-object that you don’t have an explicit handle for (oops!) so you need to add some editor UI for deleting / clearing the data-object: OnButtonClick if(myDataObject) myDataObject.dispose() myDataObject = null;

Now you want this data object to be available to your game at runtime (that’s why you created it) however we know when you click play it gets serialised and replaced with a fresh instance. So now you need to write these values somewhere that is universally persistent, which means abusing PlayerPrefs somehow (either by poking individual values or by serialising your data object to a string and storing the whole thing.)

Note none of this is actually buggy, perhaps just broken by design, or perhaps just a case of “you’re using it wrong”. Thought it was worth a mention…

Ah! That explains somes bugs I’ve seen over the years and been unable to explain / track down / debug with Unity.

I knew that Unity was abusing C# and triggering re-instantiations incorrectly (Unity Serialization is so appallingly badly-designed that it has a habit of doing this very-wrong-thing), but I’d traced the causes of most/all other situations, and figured out how to avoid (to “un-f***” Unity) … except this one.

I’ll have to do some more tests to double-check I understand correctly what you’ve described above – I may be over-estimating the impact, or misunderstanding completely. It’s complicated!

One example: I had a small scene that would randomly end up with two copies of a singleton, and I couldn’t work out how or why.

Of course, Unity support isn’t going to respond if I say “I have two copies … randomly, from day to day, without making any code changes … and I have no idea why”, so I was out-of-luck on tracing it. Ended up just writing special code to periodically detect “the impossible” (multiple copies of a singleton) and nuke one of them.

…but EditorWindow was one of the things that could trigger creation of htose singletons (IIRC), and I bet there was some bug in my code that allowed one-singelton-per-singleton-EditorWindow (or similar) – because I believed that Unity would never do something so intensely STUPID as to create two copies of the same fricking EditorWindow.

(their docs imply they wouldn’t do that; e.g. the only API they give you for getting a new instance is a singleton method)

Comments are closed.