Problems with Transform.Find and GameObject.find

Costume Swapping: Why can I not find certain objects in the hierarchy with Transform.Find or GameObject.Find, yet I can find them fine in the hierarchy search bar by the exact same name?

So I’m trying to find mesh Transforms on a model in the hierarchy (imports as a hierarchy of GameObjects) and I need to find particular children and turn them on/off. I’m doing this so I can do dynamic costume swapping for our game. The turning on/off of meshes works just fine (using MeshRenderer.enabled). So does finding SOME of the objects in the hierarchy (they’re all deeply nested children of the GameObject with the Behaviour I’m searching from).

For instance, when I search for “myCharacterName_baton”, it finds it using either GameObject.Find or Transform.Find (as it should). But when I search for “myCharacterName_hat”, it can’t find it. Both “myCharacterName_baton” and “myCharacterName_hat” are searchable from the Hierarchy Search Bar in the editor at run-time. They’re also searchable not at run-time (nothing there is dynamically added/removed). Is this a known bug? Is there something horrendously simple I’ve overlooked? Any troubleshooting help would be appreciated.

Here’s an example of what the code looks like (including the debug statements I’m using to confirm what’s happening):

foreach (string costumePiece in costumeSet)
                {
                    Transform pieceTransform = transform.Find (costumePiece);
                    Debug.Log (costumePiece + "; transform: " + pieceTransform, this);
                    GameObject go = GameObject.Find (costumePiece);
                    go.GetComponent<MeshRenderer> ().enabled = false;
                }

It always breaks on the “GameObject go = GameObject.Find (costumePiece)” line because the Transform is null… well, always when I’m searching for the hat, it finds the baton just fine.

I realize too that it would be possible to create direct references to all those components and enable/disable them that way. Unfortunately, that’s not very convenient for our artist because those references get destroyed every time he re-imports the models. Dynamically grabbing them at run-time creates a much better pipeline for him.

Transform.Find does not recursively search, to my knowledge. Probably the editor has a small script which does. So you might do something like this (not tested):

Transform FindChild (string name, Transform t)
{
  if (t.name == name)
   return t;
  foreach (Transform child in t)
  {
    Transform ct = FindChild (name, child);
    if (ct != null)
     return ct;
  }
  return null;
}