OnEnable and OnDisable getting called despite DontDestroyOnLoad

I have a GameObject that is set to DontDestroyOnLoad, yet when I switch to a new scene, its script’s OnDisable is getting called.

In fact, I tested it and found out OnEnable is getting called to! So when I load a new level, the script is disabled, then enabled. Maybe the script is getting reloaded because according to the docs:

Is this intentional? I thought these never got called when using DontDestroyOnLoad. If so, is there anything I can do? I don’t see a DontDisableOnLoad…

One idea that might work is to check if Application.isLoadingLevel returns true. If it does, then don’t execute the OnDisable/OnEnable functions.

Hmm…good idea. I was trying to think of some state I could check for, and that’s a good candidate. I’ll test it and see what happens.

“God at play” how’s that suggestion working for you?

I have the same issue only a little messier. I need to start a coroutine on a game object that is marked with DontDestroyOnLoad. The problem is that when loading a new level somehow this game object is set by the engine to inactive and the coroutine hits an error: “Coroutine can’t starte because the game object is inactive…”.
But I am NOT setting that gameobject to inactive! :frowning:

Anybody has this kind of issue?

I posted it here because it seem to be caused by the same issue described by you “God at play”. I’m not trying to hijack this thread.

The behaviour described is by design. The components are indeed disabled between level loads.

@floky:
Start your coroutines from Start - that only runs once. Alternatively you could turn Start into a coroutine - that’s perfectly valid.

IEnumerator Start ()
{
    // Initialize stuff here
    while (Application.isPlaying)
    {
        // Do work here
        yield return new WaitForSeconds (1.0f / framerate);
    }
}

Hmmm so my problem is more of a design problem?

I don’t know how this sounds to you but I have a special game object that acts like a manager that does something in the background only when it is asked to do so. The manager gameobject has DontDestroyOnLoad on it.

So the manager has a static function that calls StartCoroutine on the singleton instance of this manager’s script. (the singleton extends MonoBehavior of course)
This static function can be called in various places in the code. So it looks like if it’s called in the Awake of another script that executed before the engine resets the active state to true for my manager gameobject, then the coroutine from the manager can’t start because the gameobject is inactive in between scene loads.

The ugly workaround for me in this case was to use OnEnable on the manager script and set a static boolean (pendingStartCoroutine) for the manager, so that when the engine reactivates my game object it will automatically start that coroutine i need.

Hope this helps someone.

Is it correctly summarized that your base issue is that you need access to a static StartCoroutine method?

It does indeed sound like a design issue. Could you step one abstraction layer up. Why do you need this method?

No, actually I don’t need access to a static StartCoroutine method.
I actually made a singleton manager gameobject on which i can start a coroutine at different times in various scripts, but only in Awake() or Start() or in other coroutines. I’m not trying to hack unity’s design through this. (i think :smile: )
The manager gameobject is setup with DontDestroyOnLoad.

I will try to make a small demo project to show the issue that when in a scene where i have more than 2-3 scripts on gameobjects, if I try to start in the Awake of one of those scripts a coroutine on my manager gameobject, i get this error that the manager gameobject is inactive and the coroutine can’t start.
I placed a lot of debug logs and it really was inactive for a milisecond, and after that Awake() it became active. :slight_smile:

It’s tough to explain, I don’t know if I made this any clearer. But code and a test project will speak better. :wink:

Stay tuned. :wink:

Thanks for the reply AngryAnt buddy.

BTW, you are MY A.I. GOD buddy! I’ve been following your blog like crazy! You’re the best man! Keep it up.

Glad you enjoy the blog. I suppose I should get back to updating that a bit soonish.

To make sure that the manager is enabled when your other components need access, having them access it from Start is a good idea. Start is called right before the first frame of the component, so at this point all initialization should be done.

Yep. That’s the safest way my friend.
Thanks for the advice mate. Don’t know what this forum would be without people like you to help out.
Hope this thread helps someone.

I know that this thread is old, but I’m encountering an issue with 4.6.2… where Start() IS being called between level loads (With DontDestroyOnLoad set, and LoadLevelAsync). I’ve been putting off upgrading to 4.6.3 due to being very close to delivery date of game, and I didn’t really notice until recently that this is happening. I’m "pretty sure"™ that it was never doing it before. I also don’t see any mention of this in any patch notes either.

[edit]okay solved. lol[/edit]

has this design been changed lately? It seems that OnDisable is not called anymore on level transition for DDOL gameobjects

no one helping on this one? I can confirm that with 5.2.4, OnDisable is not called on new level loaded (therefore OnEnable won’t be called after the first time). Is it a bug or an intended behaviour?

It’s quite possible that this design did change. Scene management has seen some work done recently. Have you confirmed that the change is consistent for all types of level load?

It is in fact not working as intended in 2023.2.2 , I just tested this behaviour by putting a log in OnEnable and I’m called only once on dontdestroyonload, and multiple times in non persistent GameObjects

edit: This post might be old, but it’s the first popping up with different search results