Finding GameObjects and Transforms in Unity recursively with lambda expressions

Are you looking for a way to find GameObjects at runtime? Unity provides some methods to access GameObjects (or Transforms) but they are mostly based on types, names or tags and do not support recursive object trees. This article provides you with an extension method that allows you to use a lambda expression to recursively search the hierarchy.

Using lambda expressions

Let’s start by showing what I would expect from a modern environment that has .NET 4.6. compatibility. Suppose you created this hierarchy:

gameobjects

To get access to the GameObjects in the hierarchy tree, you want to be able to do something like:

private Transform _handle;
private Transform _bottom;

void Start()
{
    _handle = this.transform.FirstChildOrDefault(x => x.name == "handle");
    _bottom = this.transform.FirstChildOrDefault(x => x.transform.localScale.y == .1f);
}

What does Unity support?

In Unity, the following options are supported for finding the first instance of a GameObject or Transform:

Method Description Recursive Returns
GameObject.Find Finds by name No (but supports paths like a/b/c) GameObject or null
GameObject.FindGameObjectWithTag Finds by tag No GameObject or throws Exception
GameObject.FindWithTag Finds by tag No GameObject or throws Exception
myTransform.Find Finds by name No (but supports paths like a/b/c) Transform or null

The provided methods only provide finding by name or tag and if you change your hierarchy, searching by path a/b/c might break. What we want is one function that will search your object tree and allows you to find the first object that satisfies your search query. This can be achieved by creating an Extension Method that takes a parent Transform and predicate to recursively search your hierarchy.

FirstChildOrDefault Extension Method

The following FirstChildOrDefault method returns the first Transform in your object hierarchy that satisfies predicates like x => x.name == "deeply_nested_cube"

Here is the code. Just add it to your project:

using System;
using UnityEngine;

public static class TransformEx
{
    public static Transform FirstChildOrDefault(this Transform parent, Func<Transform, bool> query)
    {
        if (parent.childCount == 0)
        {
            return null;
        }

        Transform result = null;
        for (int i = 0; i < parent.childCount; i++)
        {
            var child = parent.GetChild(i);
            if (query(child))
            {
                return child;
            }
            result = FirstChildOrDefault(child, query);
        }

        return result;
    }
}

Suppose you have a scene with a cube deeply nested in the hierarchy like this:

nested structure

You can now use FirstChildOrDefault to get a reference to that cube. NestedTest is a MonoBehaviour attached to empty GameObject a in the hierarchy:

script

And the code looks like this:

using UnityEngine;

public class NestedTest : MonoBehaviour
{
    void Start()
    {
        var cube = this.transform.FirstChildOrDefault(x => x.name == "deeply_nested_cube");
        Debug.Log(cube);
    }
}

Look at the result in the console:

gameobjects

Now you have a tool to get access to all Transforms in the hierarchy by using lambda expressions.

A thing on performance

Some developers claim that finding elements in the hierarchy is slow. But speed is relative here. It all depends on these things:

In all cases, performance depends on the amount of items in the hierarchy and weather you use recursion. Claiming a certain method (like Find or GetComponent<T>) is slow only makes sense when you know how many objects you are dealing with.

Find, FindWithTag and GetComponent<T> are no magic functions. They go through a list of objects and try to match items. So keep in mind:

I hope the FirstChildOrDefault extension method will save you a lot of work when you are trying to find objects in the hierarchy.

Grüsse aus Berlin!
Loek