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?

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;
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.

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;
}

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;
}

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;
    }