Isolate OnDisable from OnDestroy

I want to check only if the object has been disabled or set inactive, so I can prevent it from being disabled if a certain circumstance is true. I want to ignore when it is being destroyed to prevent errors. Something like this:

function OnDisable() { 
   if (!beenDestroyed && myStaticVariableIsTrue) { 
      print ("Disabled or Set inactive");
      gameObject.active = true;
   }
}

Problem is: I don’t have a valid beenDestroyed and don’t know where to get one.

Main reason I want to do this (as I’ve explained in detail below) is because there are many scripts dealing with enabling and disabling (trough SetActiveRecursively) with objects and only a few of those are to be “protected” in this way - coincidentally some of the top most children of them.

Preamble

Following a similar question, seems like this is how OnDisable currently works, which is almost* (read below) useless:

function OnDisable() { 
   if (gameObject.active) { 
      print ("Disabled or Destroyed");
   } else { 
      print ("Set inactive");
   } 
}

Possible Solutions

(A) OnDestroy is only called after OnDisable, so that doesn’t help. try and catch simply don’t work.

(B) If there’s no way to grab a value for beenDestroyed we could remove it, which will bring up 3 lines of error per object:

(1) !IsDestroying()
    UnityEngine.GameObject:set_active(Boolean)
    TestOnDisable:OnDisable() (at Assets/TestOnDisable.cs:9)
    Assert in file: Assets/TestOnDisable.cs: 9
(2) !gameObject.IsActive()
    Assert in file: C:/BuildAgent/work/b0bcff80449a48aa/Runtime/Misc/GameObjectUtility.cpp at line: 853
(3) !m_IsActive
    Assert in file: C:/BuildAgent/work/b0bcff80449a48aa/Runtime/BaseClasses/GameObject.cpp at line: 72

I could ignore the many, many lines due to many objects in scene. Because they don’t really matter in this case. The function is pretty much just that. But that would make it very difficult to use/read the Debug Console otherwise and I fear they might actually have some negative effect.

(C) DontDestroyOnLoad probably might be used instead. But it would increase complexity in the code. A lot. I hate using it.

(D) And, of course, I could try and modify so many scripts to prevent disabling these specific objects to begin with… But using it this way would make much more sense programatically while keeping all the scripts much cleaner!

Appeal

Pretty please, any ideas? :slight_smile:

I would try another approach: create your own SetActive function, and avoid disabling those that satisfy some condition - with some special tag, or with a special script attached, etc. You could write a SetActive recursive function like this:

static function SetActive(obj: GameObject, onOff: boolean){
  if (!obj.GetComponent(SpecialScript)){ // only affect objects without SpecialScript
    obj.active = onOff; // set passed object ative/inactive
    for (var trf: Transform in obj.transform){ // repeat for its children
      SetActive(trf.gameObject, onOff);
    }
  }
}

If you want to activate/deactivate the children independently of the parent, just move the for loop outside the if.

Obviously, you can change the condition to whatever you want - this was just an example.

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;
	}