nested x.Find() or hierarchy mimick?

Hi!

This is not a scripting help question, it’s more of an opinion sharing thread.

The documentation says we can use Find() with a string mimicking a transform/gameobject hierarchy to find a child.

You can use it in these two ways with a Transform:

//Example one
TransformFour = TransformOne.Find("TransformTwo").Find("TransformThree").Find("TransformFour");
//Example two
TransformFour = TransformOne.Find("TransformTwo/TransformThree/TransformFour");

(The GameObject version only has the static method in the class so you can’t call it on an instance)

ObjectFour = GameObject.Find("/ObjectOne/ObjectTwo/ObjectThree/ObjectFour");

Aside from the obvious that I think it would probably be less performant to call a search for a child inside a transform multiple times, (but that’s only if you don’t do the hierarchy mimick where it skips looking through the whole children list looking for the same string name) in terms of code readability, I think it’s easier to read and understand the first example. However the second example is a shorter line and probably faster to run.

I’ve seen multiple people that do it like the first example or don’t know that the second one is possible.

If you take into consideration that the line gets called once at Start() and never again,
is there an actual difference?
Which one do you use and why?

Thank you!

I generally don’t use either one, I prefer assigning references directly from the inspector or when they are Instantiated etc…

If I had to pick one though I would use the nested path version. It’s one fewer method call and it requires less null-reference handling.

I’ve never done either, so I would say profile it. In the end, they may be exactly the same. To me, there are just better ways to set it up.

Finding things in the hierarchy by name is always gonna be flaky. Occasionally you may have to do it for when you have an imported animated object, but by and large it should be avoided. Even then, you should only call it once and cache the result.

Much better to do manual assignment in the inspector, or GetComponentInChildren, or something like that.

If transform.Find is being called enough for the performance difference between these two to matter then THAT is a problem with your code.

Personally, I’m scared of setting references manually in the inspector ever since Unity had a bug or something where all my references were reset.

Initializing object references at Start() is a common thing to do or so the documentation says.

I guess I’d prefer the second of these, but honestly I’d prefer neither. In almost every case, it would be better to have a field on the root object that directly references the child in question.

In the few others (supporting legacy objects, perhaps), it would usually be better to do something like GetComponentInChildren than to rely on a particular Transform hierarchy.

These bugs are rare. Additionally, version control can lessen the sting of this kind of bug.

1 Like

And generally, if your reference got messed up by a merge error, you want things to fail, as early as possible.* It’s infinitely better catching an error during development than having it work “almost right” and make it into the release build.

The only case that you want your code to be generous and make the best of bad input is when it’s something that you don’t have full control over.

*Speaking of which, consider validation (as in, code that can run before a build to ensure all data is correct). It’s been extremely useful in our current project.

Using unity since more than 7 years by now, it never lost a reference (unless the typename was changed, the reference deleted, the field renamed or set by an Editor Script without setting it dirty) but no way it would loose all references.
Some of my projects are already a few years old, updated multiple times and references, set right at the start of the project are still there.
Maybe you changed your entire namespace (idk of you’d loose references then?) or screwed your assembly or scripts folder (like setting it to a editor one).
Also if you are using any source control, you can just rewind.

Setting references in the Editor should not be scary for you as it is a common way to link things up.
If you rename or reparent your objects, you don’t want to change your code.