Unable to find inactive GO parented to Canvas

For some reason, GameObject.Find can locate inactive GOs except when they are a child of a Canvas GO (but there’s no problem if they are under Canvas/UI ). I found this out just now while changing my UI setup so all UI elements are parented directly under Canvas since buttons weren’t working if they were under Canvas/UI. But now Find can’t locate the UI elements that need to start inactive. I’ve eliminated all other possible causes of the problem since it CAN find these same GOs if I start them activated, so there’s nothing wrong with the string being used for the name, etc.

What the dickens is going on?

[Edit: I should add that I’m using the full pathname]

Doesn’t anyone know anything about this? I confirmed that GameObject.Find is still locating other inactive objects that are outside the Canvas GO, and it used to (earlier today) also locate inactive objects under the Canvas GO itself until I removed a redundant child GO labeled “UI” which also had a canvas as a component. I additionally confirmed that GameObject.Find can locate these same GOs so long as I manually activate them first (which isn’t necessary in any other part of the hierarchy). Is there a bug which prevents Find from locating inactive objects that are children of a GO with a Canvas attached?

Another strange thing: the following code (which hasn’t been changed) used to catch cases in which Find returned null, but now it generates an error and never gets to the line which checks for a null result:

var NewActiveGO = GameObject.Find(GOName).gameObject;
if (NewActiveGO != null)
{
.
.
}

Hey Bob,

I have run in to similar issues, though I am surprised that GameObject.Find(GOName).gameObject worked for you before. That has always failed for me.

I seem to have always been forced to check the object for null before trying to get the gameObject from it.

Which usually looks like this:

var foundGameObject = GameObject.Find(GOName);
if(foundGameObject == null)
{
return;
}

As for the original post, using GameObject.Find is extremely slow as it parses your entire hierarchy every time you call it. I would suggest holding a reference in a manager somewhere and using that to toggle your objects on and off.

Alternatively, you could also use tags which will work whether the objects are on or off and are also considerably faster if you don’t have the time to setup a larger manager.

I’ve been using the full pathname, which may be why Find usually works even for inactive GOs. And I use code which checks whether it’s null or not (as I mentioned in my third note above), but that’s suddenly failing now for objects under the Canvas GO.

I just put together a test project and I was not able to reproduce your results.

Which version of Unity are you using?

My test checked GameObject.Find on two objects, one under a canvas and one at the root.

GameObject.Find was not able to find either of the objects that were disabled but was able to find them when I enabled them.

Have you tried only disabling the components directly? This would leave the GO active for finding later but would disable the components you needed.

I’m using 5.0.1f. When you tested GameObject.Find, did you use the full path or just the name? I always assumed that if you give it the exact path then it doesn’t need to search and so it locates even inactive objects. It used to work for me even under a canvas when I mistakenly had two canvas-equipped GOs arranged one under the other, and then the individual UI elements arranged under the second. Removing the redundant canvas-equipped GO caused Find to be unable to locate GOs underneath the remaining canvas GO, or at least it doesn’t return a correct value. In my case, some of my code needs to search specifically for a name or path rather than having a reference to the GO.

Yes, I was using the full path, I am using Unity 5.5.

Here is a qoute from the documentation:

Here is the code I was using, I was able to get the messages to stop but turning the game objects on. I would suggest switching to tags to future proof your project.

    void Update () {
        var foundObject = GameObject.Find("baseCanvas/offGO");

        if (foundObject == null)
        {
            Debug.LogError("Cant Find it");
        }


        var otherObject = GameObject.Find("GameObject/GameObjectOff");

        if (otherObject == null)
        {
            Debug.LogError("Cant find the other object");
        }
    }

Thank you for your help. I was doing something essentially identical to the above code, except I would get system error messages (not my own Debug.Log message) at the line where GameObject.Find is used, rather than just getting a null value and then a Debug.Log message after the null value was detected by the IF statement. I don’t think I’ve ever seen that happen before.

Update: I found that I can make it work again just by parenting the GO to literally any intermediate GO between it and the one that has the canvas component - e.g. Canvas/Bob/ThisGO. And any buttons will also work under that arrangement so long as “Bob” is empty or at least doesn’t have its own canvas attached, apparently. But if the arrangement is Canvas/ThisGO it doesn’t work.

1 Like

Glad you found a work around!