- Home /
Get all children gameObjects
I'm trying to get all the children gameObjects,
from an Empty parent to which I have applied a script,
so I can act on each of the children with the same script.
Answer by Statement · Dec 11, 2013 at 12:32 AM
See the `Transform` docs for API details. I'll provide two examples below.
The fact that
Transform
works with `foreach` is not well documented, but Transform implements `IEnumerable` whichforeach
uses. The current (Unity 4.3.1f1)IEnumerable
implementation thatTransform
provides is callingchildCount
andGetChild
on each iteration. A curious reader can check this themselves by navigating to theTransform
class in MonoDevelop where the decompiled source is readable in the Assembly Browser.
To explain the same thing another way:
You'd expect that with Transform
, Unity would offer a call such as, say, "allChildren". So you'd do something like:
foreach (Transform child in transform.allChildren() { . . .
However, Unity do not do that. For better or worse, they make "transform" magically supply "all of its children" when it is in a situation such as a foreach.
So somewhat confusingly, you only have to write:
foreach (Transform child in transform) { . . .
using UnityEngine;
public class PrintChildren : MonoBehaviour
{
void Start()
{
WithForeachLoop();
WithForLoop();
}
void WithForeachLoop()
{
foreach (Transform child in transform)
print("Foreach loop: " + child);
}
void WithForLoop()
{
int children = transform.childCount;
for (int i = 0; i < children; ++i)
print("For loop: " + transform.GetChild(i));
}
}
If you wanted to get the game objects of the children (which will be the Transforms, not the GameObjects), just access `gameObject` of the child
Transform
in each iteration.
Thank you! I'm relieved this is so plain! I was thinking of a for loop, but didn't know the existence of GetChild(). Your post fixed it!
I'd like to share some personal views on this as well, so take it as advice rather than hard fact. Also, this is a community so I am writing it in a form directed to any reader, and readers come in varying skill levels. Please don't take it as directed especially to the OP. For example you may know foreach
and for
very well, but the next reader might not, so I'll keep it here. The only reason I put this disclaimer on is because I've noticed people get offended when I try to share some of my views, and I am only trying to help the next person.
for
is a good choice for you to use, especially when you are learning the language as it'll recur time and time again in your code and other code you read. It's also one of the most basic ways to work with collections and you really should get comfortable with it.
for
also happens to be a slightly more perfor$$anonymous$$g option than foreach
(tiny, tiny, don't bother optimizing this unless you know for a fact it's a problem in your code base).
In most cases you might want to use foreach
ins$$anonymous$$d, because it's easier to read, easier to maintain and faster to write. I don't care too much about it being faster to write, but it's a lot less complex to read.
If you need the index of the child, a for
loop is likely a better choice.
That said, it's like a basket of apples. In the end, it doesn't really matter that much as long as you solve the problem you wanted to solve. If you feel like you start to worry about if you made the right or wrong choice, but don't know why or how, stop worrying right now and continue using what you already are using. It's not a big matter until you appreciate more intuitively why one may be preferred over another. I've seen people (especially myself) worry about silly things like "should I use A or B when they both accomplish the same goal? A is better at X and B is better at Y." Is either X or Y a real problem that you need to solve? If not, pick any of A or B and continue working until you hit a real problem. Don't cause problems by trying to solve problems, if you can :) Especially those problems that really doesn't add any kind of value.
Once you start learning more and more about coding and get deeper down the path of this art, you'll find that there are a lot of other ways to deal with collections of items. Don't worry about that until you are comfortable with your current level. This is far from a challange or a hint that you are behind in your learning and should catch up. It may do you more harm than good to rush out to use more advanced solutions because you may not understand what it actually does for you (harm or good). I just wanted to let you know that this is a good starting point, but don't get surprised if you see other ways of working with collections in general.
It's a good point to start looking at other approaches when you want to learn something new, get stuck, or want to get more productive.
Thank you very much for all this @Statement! I'm always open to learning new things, but the idea is indeed to take things step by step and not delve into incomprehensible things when I'm not even able to master the basics. So I'll keep an eye open for other ways of working with collections (or other new things in general) and won't freak out when I don't understand them.
At any rate, what I wanted to say is that working on a real project (as unambitious as $$anonymous$$e might be) is just great to learn tons of stuff: I like the idea of being stuck on a problem, thinking it through and sometimes finding the solution. And I definitely LOVE the idea that when I definitely can't find the solution to my problem, there are friendly people --like you!-- who will take time to help me (as well as countless others) out!
Thank you again and have a great year in 2014!
Ari ;o)
Hi, I am trying to do something similar, but in the Editor Script world, where it seems I cannot inherit from $$anonymous$$onoBehaviour, or instantiate a $$anonymous$$onoBehaviour class in my Editor Script. So it seems I do not have access to transform. Do you know if there might be another way to get a list of GameObjects in a scene, from the Editor Script side?
Alternatively you could do this:
Transform[] allChildren = GetComponentsInChildren<Transform>();
foreach (Transform child in allChildren)
{
child.gameObject.SetActive(false);
}
That's not really an alternative. It was already suggested in robertbu's answer below. There are two major differences:
GetComponentsInChildren also return components on this object, not only on child objects.
GetComponentsInChildren also return components on deep nested children.
This answer actually shows the way to iterate through the immediate children only.
"GetComponentsInChildren" is actually a bad name for what it does. A better name would be "GetComponentsIncludingDeepChildren". So "GetComponentsInChildren" actually returns the same as "GetComponents" and additionally every matching component on any nested children.
GetComponentsInChildren is mostly useful when using it for a specific component type. However Transform makes the least sense as it will include the parent's transform and all nested children as well.
Answer by robertbu · Dec 11, 2013 at 12:16 AM
I believe you are looking for GetComponentsInChildren(). There is an example on the reference page. A couple of notes:
This is a recursive function, so it finds all children not just immediate children.
I believe this also returns the parent game object if it also has the specified component. So if your 'Empty parent' has the specified component, it will be in the array returned.
Your code will be something like:
yourScripts = GetComponentsInChildren<YourScriptName>();
foreach (YourScriptName yourScript in yourScripts) {
yourScript.DoSomething();
}
Answer by PlexusDuMenton · Mar 24, 2019 at 02:03 AM
For the lazy boi :
public static class ClassExtension
{
public static List<GameObject> GetAllChilds(this GameObject Go)
{
List<GameObject> list = new List<GameObject>();
for (int i = 0; i< Go.transform.childCount; i++)
{
list.Add(Go.transform.GetChild(i).gameObject);
}
return list;
}
}
Later in you can you can simply Call this :
gameobjet.GetAllChilds()
Answer by Cassos · Dec 12, 2019 at 09:02 PM
If you want to get every single child transform of a transform use:
List<Transform> GetAllChilds(Transform _t)
{
List<Transform> ts = new List<Transform>();
foreach (Transform t in _t)
{
ts.Add(t);
if (t.childCount > 0)
ts.AddRange(GetAllChilds(t));
}
return ts;
}
This is extremely inefficient for many reasons. First of all you create many Lists if you have a deeper nested structure. Also in almost all cases a recursive approach is less efficient than an iterative approach. Even it's relatively unlikely that this happens but in theory you could run into a stack overflow if you have really deep nested objects. In almost all cases just using GetComponentsInChildren is way simpler. It gives you almost the same result with the exception that it will also include "_t" (the root object) as well.
If you really want to manually iterate through all children you want to do something like this:
public static class TransformHelper
{
public static List<Transform> GetAllChildren(this Transform aTransform, List<Transform> aList = null)
{
if (aList == null)
aList = new List<Transform>();
int start = aList.Count;
for (int n = 0; n < aTransform.childCount; n++)
aList.Add(aTransform.GetChild(n));
for (int i = start; i < aList.Count; i++)
{
var t = aList[i];
for (int n = 0; n < t.childCount; n++)
aList.Add(t.GetChild(n));
}
return aList;
}
}
This is probably faster and more memory efficient. Also allows the reuse of a List to avoid garbage generation if it should be called frequently. It also does not allocate any memory for the IEnumerable like in your foreach version. The enumerator implemented in the Transform class will just use childCount and GetChild anyways. So you can avoid all the creation of the enumerator and just use them in a loop yourself without allocating any garbage.
The above code implements a breadth-first order. If you want a depth-first order you probably want to do it recursively since that's a bit easier to achieve this ordering:
public static List<Transform> GetAllChildrenDepthFirst(this Transform aTransform, List<Transform> aList = null)
{
if (aList == null)
aList = new List<Transform>();
aList.Add(aTransform);
for (int n = 0; n < aTransform.childCount; n++)
aTransform.GetChild(n).GetAllChildrenDepthFirst(aList);
return aList;
}
Note since both methods will create a List if none is passed you can simply use it like this:
List<Transform> childs = someTransform.GetAllChildren();
Note since you can actually pass an existing list to the method you can actually use it on several roots in a row and accumulate all children from all those roots in one list. Since the method does not clear the list passed the child elements are simply added at the end.
Answer by BiomotionLab · Jan 23, 2020 at 09:06 PM
Thanks for the tip! After some fiddling, here's a slightly cleaner version. It doesn't return the parent itself.
static List<Transform> GetAllChildren(Transform parent, List<Transform> transformList = null)
{
if (transformList == null) transformList = new List<Transform>();
foreach (Transform child in parent) {
transformList.Add(child);
GetAllChildren(child, transformList);
}
return transformList;
}
Note, to make it back to an extension method do this:
public static class TransformExtension {
public static List<Transform> GetAllChildren(this Transform parent, List<Transform> transformList = null)
{
if (transformList == null) transformList = new List<Transform>();
foreach (Transform child in parent) {
transformList.Add(child);
child.GetAllChildren(transformList);
}
return transformList;
}
}
Your answer
Follow this Question
Related Questions
Add Pointer Down event trigger only to parent object. 1 Answer
Multiple Cars not working 1 Answer
C# Children of GameObject has it's script disabled after SetActive(false) and SetActive(true) 1 Answer
C# Child GameObject Disabled Script SetActive(false) 1 Answer
Distribute terrain in zones 3 Answers