- Home /
transform.root and empty root game objects don't play nice
A handful of my scripts need to use transform.root due to nested colliders in their parent object. This is not a problem when the base object contains the component I am trying to retrieve, typically code like below after a succesful raycast hit.
EnemyHealth e;
e = hitInfo.collider.transform.root.GetComponent<EnemyHealth>();
e.SomeMethod(value);
But now I've decided I have too many objects in my scene and I would like to group them into empty game object 'folders' as per most of the community's agreement. Subsequently the above code is broken because root now references an empty game object. I tried doing this,
EnemyHealth e;
e = hitInfo.collider.transform.GetComponentInChildren<EnemyHealth>();
e.SomeMethod(value);
but it doesn't always find the component. Is there a way to use transform.root and empty root game objects correctly? If not, is there an alternative to using transform.root in my case?
Answer by Bunny83 · Jan 28, 2013 at 04:59 PM
Sure, use your own "root"
Here are some extension methods i just wrote from scratch:
public static Transform GetRoot(this Transform aObj, int aLevel)
{
var tmp = aObj;
var list = new List<Transform>();
while(tmp != null)
{
list.Add(tmp);
tmp = tmp.parent;
}
list.Reverse();
return list[Mathf.Clamp(aLevel,0,list.Count)];
}
public static T GetNextParentComponent<T>(this Transform aObj) where T : Component
{
var tmp = aObj;
while(tmp != null)
{
var comp = tmp.GetComponent<T>();
if (comp != null)
return comp;
tmp = tmp.parent;
}
return null;
}
public static Transform FindParent(this Transform aObj, string aName)
{
var tmp = aObj;
while(tmp != null)
{
if (tmp.name == aName)
return tmp;
tmp = tmp.parent;
}
return null;
}
Just place them in a static class somewhere. The usage should be clear, but just in case:
hitInfo.collider.transform.GetRoot(0); // returns the same as .root
hitInfo.collider.transform.GetRoot(1); // returns one object before the actual root
hitInfo.collider.transform.GetRoot(2); // and so on...
// If you have a certain script on the "root" object use
hitInfo.collider.transform.GetNextParentComponent<MyScript>();
// Find the nearest parent that is named "MyParent"
hitInfo.collider.transform.FindParent("MyParent");
edit
Fixed the generic parameters which aren't displayed since the last update. Replaced them with lt / gt
[$$anonymous$$eta] It's getting worse.... Now angle brackets are recognised for "List" and "GetComponent" but not on custom generics... Even worse if i replace all brackets with lt / gt the ones after GetComponent and List aren't displayed... Now we have pure inconsistency.
You wrote "methongs" ins$$anonymous$$d of "methods" lmao, thanks for the answer!
Also, many kudos for creative use of $$anonymous$$athf.Clamp. Is there anything clamp can't do?