Pages

Monday, December 8, 2014

Unity: Traversing GameObjects hierarchy

Traversing gameobjects in scene one by one is very common task when working with Unity. It usually includes two things: you want to traverse scene hierarchy and you want to do something with each hierarchy node.

In this article I will build a class that solves this once and for all. You can use this class for any processing on the particular gameobjects as the traversing is divided from processing.

Lets name our class HierarchyUtils. It will hold some static methods and it also defines delegate. We will also put it into separate namespace, so we can add other useful utility classes into it in future:

This delegate method is key in splitting traversing and processing part. The traversing part will call any method that meets delegate definition - any method returning void and taking two parameters: GameObject and int.

So, let's say we have some GameObject and we want to traverse all its child gameobjects. We will add these two methods to our class:

Call the first method with root gameobject you want to start from. It creates handler, which is ProcessNode method. This method complies delegate definition, so we can handle it to IterateGameObject. The handler here is only simple one - it prints name of each gameobject and also its depth within hierarchy. But you can do here whatever you want.

Our solution is working. It is up to you which handler you pass to IterateGameObject method, but you do not have to write traversing every time.

Now, we will add one more method to HierarchyUtils. We can call this method instead of IterateGameObject. The signature will be:

This method will traverse whole scene. And more, it will dive only into gameobjects whose names begin with names in aFilterNames. In Unity you do not have easy access to root gameobjects. You have to find gameobjects that do not have parent. Let's say your hierarchy is like this:

There is 5 root objects. You want to traverse scene, but only for root objects that are in foreground or background tree. Your aFilterNames parameter will then look like {"fore", "back"}; (remember, that names in our filter says: "stars with").

We first take all gameobjects in scene. Then we check one by one. If has parent then it is not root gameobject. If root node, but its name does not start like any filter in passed filters list then we do not iterate on this gameobject. If in list we again call our IterateGameObject method with root gameobject.

Here is example of usage somewhere in your code, which will print indented gameobject names: