Execution order of OnDisable and OnDestroy between different objects - and possibly even more event functions

Hello everyone,

the exact same question has already been asked six years ago but the posts in the topic did not answer the question and later discussions were contradicting, so please forgive me for asking again.

The documentation states that Awake and OnEnable are not reliably called in a specific order except in one object. So an object A’s Awake will always be before OnEnable but other object’s OnEnables may happen before object A’s Awake.

I noticed this seems to be the same for OnDisable and OnDestroy. Object B’s OnDestroy might be called before Object A’s OnDisable. Is this intended? It is not documented. Also, it is different between editor and build? This question was also wondering but never got an answer. Is OnDisable/OnDestroy execution order done per object?

I found this discussion: We have Awake, OnEnable, and Start. Why only OnDisable and OnDestroy? in which @Kurt-Dekker states that OnEnable() pairs with OnDisable() but the context is different. In the same thread, @spiney199 suggests using OnDisable() to do things that should happen before another object is destroyed. That would only work if OnDisable() was called before all OnDestroy()s which I observed is not the case.

I can change my code to work in any case, but this is quite essential, so I’d like to see a definitive answer in the documentation. The diagram is also not helpful - it displays Awake and OnEnable in the same block but it also displays Update and LateUpdate in the same block which makes me doubt I can rely on those (I am refering to this page Unity - Manual: Order of execution for event functions).

For the last thing you touch on - LateUpdate runs after Update has run on all objects. The ordering in particular is Update happens on all scripts, then animation moves all bones, then LateUpdate happens on all scripts. This is what allows LateUpdate to post-process animations that are set in Update.

For OnDestroy/OnDisable, I’m not quite sure. I don’t think I have ever run into a situation where the ordering of OnDestroy/OnDisable between objects is important. You might want to raise a documentation bug if the current ordering isn’t documented anywhere.

Thanks for your answer. Yeah, using LateUpdate for post-processing animations is an example the documentation mentions, too, and a thing I have done myself. That means however that the markup of the flowchart is inconsistent / meaningless (the grey areas do not always mean "only consistent within one object).

Is there anything to open a documentation bug except the link on the documentation pages? I’ll use that for the OnDestroy/OnDisable thing.

And well, if you can rely on a specific order, you can more easily write code that cleans up things when scenes are unloaded / the game ends, but most importantly the behaviour should be documented correctly.

The gray blocks on the script life cycle flowchart are just a rough categorization, they aren’t intended to show what’s executed together.

Awake and OnEnable are really the same message, always executed right one after the other, with the only the difference being that Awake is only called once.

When a scene is unloaded or the game shuts down, OnDisable and OnDestroy behave the same way, always executed right after each other for every object. However, when destroyed with Object.Destroy, OnDisable is called immediately but the destruction is queued and OnDestroy called at the beginning of the next frame, so you first get all the OnDisable calls and only later all the OnDestroy calls together.

There are also no ordering guarantees for OnDisable/OnDestroy, the objects get cleaned up in an effectively random order, even across scenes and ignoring the scripts’ execution order.

There’s a trade-off between performance and ordering, guaranteeing a fixed order requires you to queue up and sort those messages. Unity provides quite a bit of guarantees and control for initialization but opted to provide only minimal guarantees for destruction and shutdown.

I also think that destruction/shutdown is a bit limited. Like, if you want to spawn something when an object is destroyed, there’s no good way to know if the object was explicitly destroyed or is cleaned up due to the scene unloading or the game shutting down. Or, if you do pooling and want to rescue something from an object being destroyed, the object is irrevocably marked for destruction and will be destroyed in the next frame. In those cases, you’ll have to add your own messages that you call before actually destroying objects.

But I’ve learned to not rely on any ordering in OnDisable/OnDestroy and structure my cleanup logic to work regardless. If the scene is unloaded or the game shuts down, you often also don’t need to do any cleanup since everything is destroyed anyway.

2 Likes