Why do OnDisable and OnEnable get called when hitting undo?

Say I have a MonoBehaviour script with the [ExecuteInEditMode] attribute.
Then if I make any change to the attached object (or any parent), e.g. moving the transform, and then hit ctrl-z to reset it, OnDisable and then OnEnable get called on my component, effectively resetting it. It’s very problematic for me and I don’t understand why it happens. I only want OnEnable and OnDisable to be called when the component is enabled or disabled… Or at least if I had a way of knowing whether it’s a ‘true’ OnEnable or being called from a undo operation, that would be enough to workaround it.
I can’t find any documentation for this behaviour or any mention of it online.
Any way to disable this or any workaround?

Just remove the ExecuteInEditMode

This is likely because of serialization which serializes the component, destroys it, and reserializes it.

You can either make your state serializable like any public field, or you move that editor-only state to a SessionState instance which even survives domain reload.

Thanks but I can’t because the component is a tool meant to be used in edit mode

Hm I guess it makes sense that state has to be de/serialized for an undo operation. But in my case losing state is not the problem. Basically my component spins up an intensive process which runs in a separate thread. I want that process to keep running as long as the component is enabled but kill it when the component is disabled. I don’t care about undo/redo. But as far as i can tell there is no way for me to tell when the component is ‘really’ disabled or whether the user just hit ctrl-z! I can’t think of any workaround for this that isn’t very awkward. The best idea I have so far is to attach a callback to the undo event and ignore the OnDisable/OnEnable calls that happen right after. But that would be fragile and I wish it wasn’t necessary

There’s a tool for that. The EditorTool class. :wink:

Hooking into Undo events. But yes, it’s awkward. But that’s what happens when you try to make editor tools from runtime MonoBehaviours.

Ah lol, fair point. I’ll look into it, thanks

For anyone else looking, found an easy solution:

Within OnEnable/OnDisable you can check the Undo.isProcessing flag to see if it’s being called as part of an undo/redo operation or a true enable/disable.

3 Likes