- Home /
Is it possible to determine if OnDisable() is being called from parent.SetActive( false ) or self?
I have a class derived from monobehaviour.
For various reasons when OnDisable() is called I need to know whether it was triggered by:
a) the GameObject it is a component of having SetActive( false ) called on it, or...
b) ...whether SetActive( false ) was called on a GameObject higher up the hierarchy
is it possible to tell, and how can you do it?
**N.B. I couldn't find any questions that asked this, and since I have now solved this problem I thought I would share the information with the community by asking the question and answering it myself.
Answer by darbotron · Oct 20, 2013 at 08:46 PM
There are two properties of GameObject that give information about its active state:
GameObject.activeSelf - this flag is only set by use of SetActive() on the GameObject it is a member variable of
GameObject.activeInHierarchy - this flag is also set by SetActive() on the GameObject, but also by use of SetActive() on any parent GameObject
See the GameObject documentation: http://docs.unity3d.com/Documentation/ScriptReference/GameObject.html
also see the 'GameObject active state' for more detail on how these flags work: http://docs.unity3d.com/Documentation/Manual/UpgradeGuide3540.html
Based on tests I did, it seems these flags are set by the Unity code before OnDisable() is called.
Given this information you can use these flags to determine which case a), or b) is true in the question:
a) both flags will be false in this case (SetActive( false ) was called on this object)
b) activeInHierarchy will be false, and activeSelf will be true (SetActive( false ) was called on an object upstream in the hierarchy)
Answer by Hoeloe · Oct 20, 2013 at 08:32 PM
The only way you could do this is by wrapping up the function SetActive within the class itself. There, you could set a flag in the wrapper, which tells the program "I am being called from within this object", that you would reset at the end of the OnDisable method. That way, if the flag hasn't been set, then it is being called from elsewhere, while if it is set, then it is being called from within the current script.
This would do it too, but in my use case I can just use the Unity flags :)
Ah I see, I wasn't sure whether those would work for your case, but if they do, then that's great.
Your way is more bulletproof and generic, have chosen it as the best answer :)
Your tests will probably prove to work well, my method is more general use, and is guaranteed to work as expected (using Unity's flags may produce problems if they do odd things, as you can't see the source code), but may be less readable or efficient than using Unity's flags, depending on how you use them.
LOL! after more thought - I've re-voted my (edited!) answer as the correct one...
Here's why:
There are only 3 valid states of these flags (let's call activeSelf "S", activeInHierarchy "H")
S: true H: true
S: true H: false
S: false H: false
S: false H: true - NOT VALID
OnDisable can only be called by 3 transitions:
state 1 to 2 if SetActive( false ) called on upstream object
state 1 to 3 if SetActive( false ) called on self
state 2 to 3 if SetActive( false ) called on self
which matches my original answer - thanks for the help dude, interesting hour or so of discussing this ;)
Your answer
Follow this Question
Related Questions
Can a parent SetActive a child GameObject anymore 2 Answers
How can I get my own gameobject? 2 Answers
Can't activate game object. 3 Answers
Zombie won't die 2 Answers