Ok, this one is a little difficult to explain.

  • Let's say that you have multiple characters in your game.
  • Each character (prefab) may have a different bone structure & bone names.
  • Certain GameObjects (in the prefabs) you renamed for simplicity. (E.g. each character has a GameObject named "Head")

Now, given an OnTriggerEnter() Method, you find the "root" GameObject from the collider.

From this point, how do you locate the "Head" GameObject, from the root of this GameObject?

Keep in mind, each GameObject (character) contains a Head. You want to find this particular GameObject's Head.

Code I've tried: (which returns a null reference)

private void OnTriggerEnter(Collider char)
{
    var en = char.gameObject;
    var head = en.transform.Find("Head");
}

Is this possible to do without explicitly typing out each hierarchy, of each different type of bone structure?

3 Answers

0
Penjimon On

Hellium was correct in the comment. Please credit him or her for their efforts!

Here is a simplified version of the answer:

    public static Transform FindDeepChild(Transform aParent, string aName)
    {
        Queue<Transform> queue = new Queue<Transform>();
        queue.Enqueue(aParent);
        while (queue.Count > 0)
        {
            var c = queue.Dequeue();
            if (c.name == aName) return c;
            foreach (Transform t in c) queue.Enqueue(t);
        }
        return null;
    }
1
Kil jeaden On

Find does not descend the Transform hierarchy. Find will only search the given list of children looking for a named Transform if no child can be found, null is returned. In other words it won't look in the children of its children. If you wish to use Find on child that is already child then you must access it like a path using /, eg. transform.Find("Body/Head").

In general string reference like that is a very bad idea, one way you could do it is by creating an empty script (Let's say Head.cs) and attach it to the child of the parent GameObject then instead of looking for the transfrom by string reference you can look for component Head.cs

It would look something like this:

private void OnTriggerEnter(Collider collider)
{
   //Where Head is an empty script attached to the Head.
   var head = collider.GetComponentInChildren<Head>();
   //Do something... Logging the name for example
   Debug.log(head.transfrom.name);
}
0
Community On

Here is the more simple verson:

public static Transform FindDeepChild(Transform aParent, string aName) {

    var headList = collider.GetComponentInChildren<Transform>(true);

    foreach(var it in headList)
        if (it.name == "Head")
            return it;
    return null;

}