How To Get List of Child Game Objects

Sometimes a game object has child game objects. Likewise, a game object can have a parent. In the past I tried getting all child game objects by using this:

List gs = new List();
Transform[] ts = gameObject.GetComponentsInChildren<Transform>();
if (ts == null) return gs;
foreach (Transform t in ts)
{
    if (t != null && t.gameobject != null)
    gs.Add(t.gameobject);
}
return gs;

But I have recently proven this is unreliable when running from the editor. I have loaded in from a collada file the main game object. In the hierarchy view, I see the game object with all of its children. However, my script returns an empty list.

Can somebody please tell me a reliable way to get child objects?
Can somebody please tell me a reliable way to get the parent game object?

A clever recursive function to obtain all the children of a game object down multiple levels of hierarchy! https://github.com/aniketrajnish/get-all-children-of-a-gameobject/blob/main/ChildList.cs

14 Answers

14

The suggestions I’ve seen from smart people like @Eric5h5 is to use the build-in transform functions, rather than GameObject.Find. Since it looks like you’re using C#, the following is also in C#:

To get children:

foreach (Transform child in transform)
{
    //child is your child transform
}

To get parent:

transform.parent;

The issue as stated before is that this returns the Transform of "transform" in the foreach loop, adding: if (child != transform[0]){} will eliminate the transform you're wanting to get children from. which would change the code to: foreach (Transform child in transform) { if (child != transform[0]){ //child is your child transform } }

@DCrosby I just checked and that does not seem to be the case. Iteration over the transform does not include itself.

I don't like this solution since it finds the child's transform and not the child itself. Maybe I'm missing something...

My solution was similar but here is the full code, and you can get to the game object itself from it: Transform[] allChildren = GetComponentsInChildren<Transform>(); foreach (Transform child in allChildren) { child.gameObject.SetActive(false); } So as you can see it's easy to get to the gameObject.

public List<GameObject> Children;
foreach (Transform child in transform)
{
    if (child.tag == "Tag")
    {
        Children.Add(child.gameObject);
    }
}

In C-Sharp you can use this code to get all the child objects with a certain tag.

I use this method. Even if your not filtering by tag, storing the children in a List is the only way to use methods like: System.Array.Reverse(Children) because Transform doesn't have a built-in GetEnumerator.

Your first line of code is incorrect. When declaring the Children list there is no need to add public in front of it. Children is a local variable, not a property. It will be available to the foreach loop anyway, because they are both on the same function scope. Also, you are not instantiating the list, which some IDEs (such as Visual Studio) will report as an error. In short, you should fix the first line to: List<GameObject> Children = new List<GameObject>();

foreach (Transform child in transform)
{
  //child is your child transform
}

This is right: GetComponentsInChildren will get gameObject’s transform as well.

foreach(Transform child in transform) is unreliable, as is GetComponentsInChildren, as they won’t traverse the entire tree of children.

This will correctly return all the children:

void Start ()
{ 
    Debug.Log("Child Objects: " + CountChildren(transform));
}

int CountChildren(Transform a)
{
    int childCount = 0;
    foreach (Transform b in a)
    {
        Debug.Log("Child: "+b);
        childCount ++;
        childCount += CountChildren(b);
    }
    return childCount;
}

No it won't, you're script returns the number of children not a list of them. Besides you can just use transform.childCount to get the number of children anyway.

As far as I know, "children" refers to the transforms on the next level only, while "descendants" would refer to every transform below this one in the tree. If the goal was to iterate over all descendants, the code example shows a way to do that recursively.

This is generically wrong, GetComponentsInChildren does transverse the entire tree of children, not just the immediate children. It might not behave correctly when used with Transform's though.

The best Answer would be a recursive function I guess …

So the function will go and look at the first Transform it finds in transform then it will do whatever you want to do (add it to a list or array or whatever) in this case it will change the active and passive colour stored in a level element… after it has done what it should it will see if the object has any children.

“!” Although this works sometimes there seems to be a real problem with the childCount function in about 50 percent of all objects it does not see the last layer of the hierarchy.

“!!” There is also one problem with this: If you add new layers OnStart of the Game and you also execute the script at the same time as these will get created it might not see them… -?- Is there any way to time this or should I just use a yield WaitForSeconds in the start function…?


public void Start () 
	{
		StartCoroutine(OverrideAllChildren(transform));
	}

	public IEnumerator OverrideAllChildren(Transform pTransform)
	{
		foreach(Transform child in pTransform)
		{
			TouchQube temp = child.GetComponent<TouchQube>();
			if(temp != null)//If it is a TouchQube
			{
				totalCount++;
				if(overrideInactive){temp.SetInactiveLight(overrideColor);}
				if(overrideActive){temp.SetActiveLight(overrideColor2);}
			}
			Debug.Log(child.name+" has "+CountChildren(child)+" children. TotalOverwritten: "+totalCount);
			if(HasChildren(child))//If it has children
			{
				StartCoroutine(OverrideAllChildren(child));
			}
		}
		yield return(true);
	}

	public bool HasChildren(Transform pTransform)
	{
		int count = 0;
		foreach(Transform child in pTransform)
		{
			count++;
		}
		if(count > 0){return true;}else{return false;}
	}

	public int CountChildren(Transform pTransform)
	{
		int count = 0;
		foreach(Transform child in pTransform)
		{
			count++;
		}
		return count;
	}

Recursive solution that returns a list of gameobjects.

List<GameObject> GetAllChildren(GameObject obj)
{
	List<GameObject> children = new List<GameObject>();
	foreach(Transform child in obj.transform)
	{
		children.Add(child.gameObject);
		children.AddRange(GetAllChildren(child.gameObject));
	}
	return children;
}

Hey @zd, That's a nice, simple solution! You can also rewrite it so that it passes a reference to the existing list with each recursion. Currently, you're going to be creating a lot of lists and then copying entries from list to list - that's a lot of overhead. You're also casting back and forth between gameObject and transform, which is additional overhead - you could work directly with transforms and then use a Linq expression at the end to convert all the entries at once.

Hi, I wrote some static methods that allow you to recursively get all children without creating new lists every time (each call adds to a master list).

public static class Utils {
	
	public static List<GameObject> GetChildren(GameObject go) {
		List<GameObject> list = new List<GameObject>();
		return GetChildrenHelper (go, list);
	}

	private static List<GameObject> GetChildrenHelper(GameObject go, List<GameObject> list) {
		if (go == null || go.transform.childCount == 0) {
			return list;
		}
		foreach (Transform t in go.transform) {
			list.Add (t.gameObject);
			GetChildrenHelper (t.gameObject, list);
		}
		return list;
	}
}

Hope this helps :slight_smile:

I ran into a problem recently where the loop was getting half way through the child count and stopping, weird…

I fixed it with this:

List<Transform> children = new List<Transform>();
  
foreach (Transform t in previousTrackable.transform)
	children.Add(t);
  
foreach (Transform t in children)
	t.parent = currentTrackable.transform;

This piece of code will place all children in an array at Start:

using UnityEngine; 
using System.Collections;
    
public class YourClass : MonoBehaviour {
    
     public GameObject[] children;
     public int i;

void Start () {
     
         children = new GameObject[transform.childCount];

         foreach(Transform child in transform)
         {
              children[i++] = child.gameObject;
         }
     }
}

Try this:

for (int i = 0; i < transform.childCount; i++)
{
    Transform myTransform = transform.GetChild(i);
}

My solution is similar to the accepted answer and simpler than many of the other suggestion. I have included the full code and tested it.

Transform[] allChildren = GetComponentsInChildren();
foreach (Transform child in allChildren)
{
   child.gameObject.SetActive(false);
}

It deactivates all of the children. You can easily get to the game object from the transform. You could just as easily use this code to make a list of all of the game objects.

A clever recursive function to obtain all the children of a game object down multiple levels of hierarchy!

Im kinda new to this. I wrote a func for search children in childs with tag. Im sure this is a bad code, but it works:

public static GameObject[] ReturnAllChildsWithTag(GameObject[] List, GameObject parent, string tag, int index)
{
    foreach (Transform child in parent.transform)
    {
        if (child.tag == tag)
        {
            List[index] = child.gameObject;
            index++;
            ReturnAllChildsWithTag(List, child.gameObject, tag, index);
        } 
        else
        {
            ReturnAllChildsWithTag(List, child.gameObject, tag, index);
        }
    }
    return List;
}
GameObject[] Joints = new GameObject[30];
Joints = ReturnAllChildsWithTag(Joints, rod_bend, "rod_joint", 0);

This could be done by using a recursive function that iterates through all the child Game objects , until it finds all the child gameobjects :

This is a function that returns "List of gameObjects "that has all the child gameobjects , of a given gameobject##

public List<GameObject> get_All_children_of_Go(Transform go)
    {
        //A new List is created to hold all the Gameobjects (children at different hierarchy level , under the gameobject (go))
        List<GameObject> al_go_ch = new List<GameObject>();

        for (int j = 0; j < go.childCount; j++)
        {
            //here we check if the List already has that game object , if not we add that to a List
            if (!al_go_ch.Contains(go.GetChild(j).gameObject))
                al_go_ch.Add(go.GetChild(j).gameObject);

            //here , we iteratively call function "get_All_children_of_Go(go.GetChild(j))" to get all the children inside "go.GetChild(j)"

            //the returned list is , Concatenated with "al_go_ch" list
            al_go_ch.AddRange(get_All_children_of_Go(go.GetChild(j)));
        }
        //Finally the List "al_go_ch" that contains all children is returned
        return al_go_ch;
    }