Implementing a function to step through a hierarchy one node at a time

Lets say we have some hierarchy built up in the Hierarchy window of Unity.

Consider this function:

public void TraverseTree(Transform t)
{
    Debug.Log(t.name);

    foreach (Transform child in t)
    {
        TraverseTree(child);
    }
}

If I call this function on the transform of the root of my hierarchy it will print the names of the game objects in the hierarchy in a depth first fashion (using recursion).

What I would like to do is instead of having the names all print out at once is to have the functionality that only when I press the space bar does the next name get printed. This way I can step through the entire heirarchy by pressing the space bar for each step.

Could someone offer an idea on how to do this?

You have transform.GetChild(int index) and transform.childcount to work with

so if you have an index

int index = 0;

you could cycle through your childs with

Debug.Log(transform.GetChild(index++ % transform.childCount).name);

Nope, that’s not recursive like OP wanted.

@ , here’s a prototype for an IEnumerator-based setup:

public class TestScript : MonoBehaviour {

    private IEnumerator<string> DataEnumerator;

    private void Update() {
        if (Input.GetKeyDown(KeyCode.Space)) {
            if (DataEnumerator == null) {
                DataEnumerator = PrintChildrenNames();
                DataEnumerator.MoveNext();
            }

            Debug.Log(DataEnumerator.Current);
            if (!DataEnumerator.MoveNext()) {
                DataEnumerator = null;
            }

        }
    }

    private IEnumerator<string> PrintChildrenNames() {
        yield return "Printing names of children of: " + transform.name;

        if (transform.childCount == 0) {
            yield return "no children!";
            yield break;
        }

        var parent = transform;
        var child = parent.GetChild(0);

        while (true) {
            yield return child.name;
            if (child.childCount > 0) {
                parent = child;
                child = child.GetChild(0);
            }
            else {
                while (child.GetSiblingIndex() == parent.childCount - 1) {
                    if (parent == transform) {
                        yield break;
                    }

                    child = parent;
                    parent = parent.parent;
                }

                child = parent.GetChild(child.GetSiblingIndex() + 1);
            }
        }
    }
}

I think it’s much easier to handle than having a field that’s a pointer to the current transform, which is what you’d end up doing otherwise. It’s also neat to know the inner workings of IEnumerators when you work in Unity, since they’re used so much for Coroutines.

3 Likes

Thank you @Baste , that works perfectly!

To be honest I am not familiar with IEnumerator and I don’t quite understand how it works.
I will spend some time on it.

P.S. Your games “Teslagrad” and “World to the West!” look great!

That’s cool. But you can also do this with a coroutine by adding just a couple of lines to the OPs code and calling it with StartCoroutine.

public IEnumerator TraverseTree(Transform t)
{
    while (!Input.GetKeyDown(Keycode.space)) yield return null;
    Debug.Log(t.name);

    foreach (Transform child in t)
    {
        yield return TraverseTree(child);
    }
}
1 Like

That is an interesting idea @Kiwasi

When I tried it, it often prints several nodes at once instead of one at a time.
The idea is there though, I am sure it can be modified.

Thanks.