OnDisable() getting called from Destroy()

So apparently OnDisable also gets called when an object is destroyed. I need an OnDisable equivalent that only gets called when the object is disabled, not necessarily destroyed. OR I need a way to check if the object is destroyed from OnDisable. OR I need a Destroy equivalent that doesn’t call OnDisable.

To a limited extent, we can tell whether OnDisabled is being messaged as a side effect of a game object being destroyed. Ideally, however, a parameter indicating the reason a component is being disabled/enabled (game object is being destroyed, or deactivated, or the component itself is being disabled) would be helpful.

In the meantime…

Inside OnDisable, check the value of this.enabled:

  • this.enabled is true when the game object is about to be destroyed (unless the component owned by said game object was previously disabled via enabled=false).
  • this.enabled is false when the object is being disabled but not about to get destroyed.

In general, checking the state of the enabled flag upon receiving OnDisable is not sufficient to determine whether a game object is about to be destroyed. For example, the same situation (OnDisable is messaged and this.enabled returns true) will occur when the game object is directly or indirectly deactivated.

Note: OnDisable is called before OnDestroy.

Found a way around this when the app is quitting, still not sure about scene changing tho.

OnApplicationQuit() is called in the execution order before all the OnDisable()s, so setting a flag in there allows the OnDisable() to have a bit more awareness of if it’s being called normally, or from the app shutting down:

	bool quitting = false;
	
	void OnDisable ()
	{
		if (quitting)
			return;

		// Do stuff as usual
	}

	void OnApplicationQuit ()
	{
		quitting = true;
	}

Necro’ing with another potential solution:

Create a “wrapper” function/method that handles destruction of game objects, and call that instead of Destroy(). One could also do this when setting enabled to false.

Pass the game object in as a parameter, then set flags or properties on the object, or perhaps change the object’s tag (personal preference in most cases, although some methods are better than others in more situations) to tell you what is happening to the object, then call Destroy() (or set object.enabled to false) in the “wrapper” function - then simply check in your OnDisable() logic for the flags you set in the wrapper to determine the proper course of action in OnDisable().

Aside: an amazing amount of functionality can be added to your systems this way, although you fairly quickly stop coding in “Unity Style” and begin coding your own way, using your wrapper library you create as you go. This is not necessarily a bad thing!

As far as I know, there’s no way to prevent this from happening, nor is there a built in way to check if the OnDisable is being triggered by the object being destroyed.

Also this.isActiveAndEnabled if this.enabled does not work for you

Thanks to the comment playsidepaul posted, I’ve found a way to get around OnDisable being called while switching scenes as well!

I have all the scene switch calls inside a persistent GameManager singleton. Every time before I switch scenes in any ways, I kept track of a “isSwitchingScene” variable as follows:

[NonSerialized] public bool isSwitchingScene; 

    private void OnSceneLoaded(Scene arg0, LoadSceneMode arg1)
    {
        isSwitchingScene = false; 
    }

    private void OnApplicationQuit()
    {
        isSwitchingScene = true; 
    }

    public void LoadSceneSync(string _sceneName)
    {
        isSwitchingScene = true;
        SceneManager.LoadScene(_sceneName);
    }

“isSwitchingScene” will be true whenever I start a scene switch, or when the game is being shut down.
“isSwitchingScene” toggles back to false after scene load.

Inside another script’s OnDisable(), I could ensure the codes aren’t executed when the game object is destroyed via scene load:

    protected override void OnDisable()
    {
        if (GameManager.Instance.isSwitchingScene) return; //don't call when destroyed 
        //do stuff
    }

Of course this does not account for cases where you manually destroy a game object during runtime, which would be considered bad practice anyways, because doing so creates memory fragmentation. You’d ideally be using an Object Pooler to create all the objects you could possibly need at the start of a scene (hence allocating all the memories from the get go as one single memory block), and always disable objects instead of destroying them.

So if you are doing object pooling, you’ll almost never destroy objects apart from when switching scenes, so my approach would be foolproof.

This might be obvious, but why don’t you check if the gameobject is not destroyed OnDisable()? As in, if this == null.
P.S. From the accepted answer, however, it might be a stupid suggestion.