Effective Hierarchy Traversal

Hey folks,

So I have a situation where I need to access a component from a specific spot in a hierarchy and I’d like some opinions on the most effective way to go about it.

Here’s my hierarchy

  • World Parent
    – Root
    — Child
    ---- BoxCollider

So I’m doing a RayCast that hits BoxCollider (meaning that it is the contents of the returned RaycastHit). I need to access a component on Root. I already have an extension method that gets the topmost parent of a Transform but unfortunately in this situation that would return World Parent and not Root.

One “creative” solution I tried was to pass a Transform as the argument in a SendMessageUpwards call that would be called on the component I need but it didn’t perform the way I had thought it might (the transform variable passed in doesn’t maintain it’s pointer on the way back out). What I mean is this:

// in class that performs raycast
Transform t = hit.transform;
hit.transform.SendMessageUpwards("Foo", t);
Debug.Log("After SendMessage " + t.name);


// in SendMessageUpwards target
public void Foo (Transform t)
{
    Debug.Log("Foo " + t.name);
    t = this.transform;
    Debug.Log("Foo " + t.name);
}

This results in:
Foo BoxCollider
Foo Root
After SendMessage BoxCollider

I’d prefer no to chain transform.parent.parent.parent… calls.

Thoughts?

transform.root

Would return World Parent which is not what I need in this instance.

World Parent is my parent for a bunch of “Root” objects.

haha, I didnt read your requirements properly.

Are you saying you have everything as a child of your world parent?

Not everything - but for sake of argument, everything that matters for this use case. World Parent is an organizational object that contains many other scene objects but there are other organizational gameobjects that contain other gameobjects of different types

So:

  • World Parent
    – Root
    — Child
    ---- BoxCollider
    – Root
    — Child
    ---- Box Collider
    …on and on

Given a raycast against any of those BoxCollider objects I need it’ corresponding Root gameobject.

something I just hacked together… should work… might need a tweak

Transform GetRoot(transform t)
{
   if(t.parent != null  t.parent.GetInstanceId() != t.root.GetInstanceId())
      return GetRoot(t.parent);
   else return t;
}

Hm, that’s not a bad thought. GetInstanceId() probably isn’t necessary due to the == overload on Transform but that might just work otherwise. Thank you sir :slight_smile:

hmm yeah true, probably dont need the GetInstanceId

I was hoping that my SendMessage hack would prove successful but it appears that Unity sends those arguments by value and never tells you. Unless it was because I was sending a Transform. (Could test by wrapping it in some other object - but now I’m just thinking out loud…)

I believe it’s because you were sending a transform. I’ve been able to pass closure functions in C# via SendMessage, which are reference only to my knowledge.