I have an older project I’m updating from Unity 4.6, and I ran into a problem with some variables not being initialized. Turns out, the Awake functions on inactive objects are not running. If I open the original project in 4.6, the Awake functions are called on the inactive objects.
Some objects have children that are inactive when they are instantiated, and the Awake functions attached to those inactive objects are no longer running. If I change the Awake functions to functions I call after instantiation, it works. Or if I make those inactive objects active in the prefab, then set them to inactive after they’re instantiated, it works.
The scripting guide doesn’t say anything about inactive objects, but there’s a tutorial that says Awake is always called, though Start isn’t: Start MonoBehaviour Methods - Unity Learn
Yes, that’s correct. I was wrong, Awake was not being called in 4.6. It’s later, when I call a function in the script that was not initialized with Awake.
It looks like the problem is with GetComponentInChildren and the way SetActive has changed. GetComponentInChildren is returning a script on a object whose parent is inactive. Since I’m not using SetActiveRecursively, only the parent is set to inactive. And now, when the parent is inactive, it’s children are still active, and so are the scripts attached to those children.
This seems inconsistent. The object’s parent is inactive, so the Awake function was not called for any of the inactive parent’s children on instantiation. But GetComponentInChildren ignores the parent’s inactive state and gets a script from the children of that inactive parent. Since those children were not initialized with Awake, when I call a function in that script, it crashes.
Looks like I now need to check activeInHierarchy before calling a script. That fixed a few other odd problems I was seeing!
In the current version of unity, SetActive is the only method you need, and that activeness is inherited by the children inherently no matter what:
Every gameobject now has properties to test if it is activeSelf and activeInHierarchy.
activeSelf is false if you’ve called SetActive(false) directly on that GameObject:
activeInHierarchy is false if either it has been set inactive OR a parent has. This one being the best tell of if the GameObject is actually active at all.
As for GetComponentsInChildren, how that works is that it skips over inactive GameObjects (activeSelf). Thing is, if you call it on an inactive GameObject, that specific GameObject isn’t skipped over… and it’ll dig into its children… but will skip over inactives within it (activeSelf). You shouldn’t call GetComponentsInChildren, or GetComponent in general, on a GameObject that is inactive, and then attempt to access them.