Search Unity

  1. Unity 6 Preview is now available. To find out what's new, have a look at our Unity 6 Preview blog post.
    Dismiss Notice
  2. Unity is excited to announce that we will be collaborating with TheXPlace for a summer game jam from June 13 - June 19. Learn more.
    Dismiss Notice

Hiow to get children gameobjects array??

Discussion in 'Scripting' started by JohnSonLi, Jul 6, 2012.

  1. JohnSonLi

    JohnSonLi

    Joined:
    Apr 15, 2012
    Posts:
    586
    GetcomponentsInChildren can return specific component array in children. What if I want to get the children gameObjects???There is no function call like GetComponentsInChildren<GameObject>().......Help me!
     
  2. BrUnO-XaVIeR

    BrUnO-XaVIeR

    Joined:
    Dec 6, 2010
    Posts:
    1,687
    Code (csharp):
    1.  
    2.     var objects = new Array();
    3.     RigidBody[] bodies;
    4.     void Example() {
    5.         bodies = GetComponentsInChildren<RigidBody>();
    6.         foreach(RigidBody body in bodies) {
    7.             objects.Add(body.gameObject);
    8.         }
    9.     }
    10.  
     
    Charles-Andrew likes this.
  3. eduardo-pons

    eduardo-pons

    Joined:
    Mar 31, 2009
    Posts:
    176
    Code (csharp):
    1.  
    2.  
    3. void Start()
    4. {
    5.       //Transform is a Component so it can be fetched with this method.
    6.       //If you have 'Transform' or any other thing that is at least a 'Component' you can have '.gameObject'
    7.       Transform[] transform_list = GetComponentsInChildren<Transform>();
    8. }
    9.  
    10.  
     
  4. KelsoMRK

    KelsoMRK

    Joined:
    Jul 18, 2010
    Posts:
    5,539
    Or turn it into an extension method.

    Code (csharp):
    1.  
    2. using UnityEngine;
    3. using System.Collections;
    4. using System.Collections.Generic;
    5.  
    6. public static class HelperMethods
    7. {
    8.     public static List<GameObject> GetChildren(this GameObject go)
    9.     {
    10.         List<GameObject> children = new List<GameObject>();
    11.         foreach (Transform tran in go.transform)
    12.         {
    13.             children.Add(tran.gameObject);
    14.         }
    15.         return children;
    16.     }
    17. }
    18.  
    Then just call it directly
    Code (csharp):
    1.  
    2. List<GameObject> children = gameObject.GetChildren();
    3.  
    It really should be documented more explicitly that Transform implements IEnumerable<T>
     
  5. eduardo-pons

    eduardo-pons

    Joined:
    Mar 31, 2009
    Posts:
    176
    1 line method :)

    Got to love these Generics!

    Code (csharp):
    1.  
    2. List<GameObject> l = new List<Transform>(transform.GetComponentsInChildren<Transform>()).ConvertAll<GameObject>(delegate(Transform p_it) { return p_it.gameObject; });
    3.  
     
  6. JohnnyA

    JohnnyA

    Joined:
    Apr 9, 2010
    Posts:
    5,061
    Neat and all but it returns the wrong answer for me (it gives current transform as well as the children and children of children), although maybe thats debatable as the OP did also say "like" GetComponentsInChildren().

    Anyway try this:
    Code (csharp):
    1.  
    2.   l = transform.Cast<Transform>().ToList().ConvertAll<GameObject>(t => t.gameObject);
    3.  
    Faster (presumably because it doesn't use get component), returns just the children, and also a cleaner and shorter line of code.

    (You will need to include LINQ)

    Or if you did want to use GetComponentsInChildren() you could write:
    Code (csharp):
    1.  
    2. l = System.Array.ConvertAll(transform.GetComponentsInChildren<Transform>(), t => t.gameObject).ToList();
    3.  
    Still faster although not by as much, slightly shorter code too :)
     
    Last edited: Jul 6, 2012
    simonpasi_XR likes this.
  7. KelsoMRK

    KelsoMRK

    Joined:
    Jul 18, 2010
    Posts:
    5,539
    So now we're doing a "write this in 1 line" competition? Clarity ftw. :)
     
  8. JohnnyA

    JohnnyA

    Joined:
    Apr 9, 2010
    Posts:
    5,061
    Just having fun, although I thought my first example was both fast and clear :)

    If we want to get shorter we could take out the superfluous generics too...

    Code (csharp):
    1.  
    2.     l = transform.Cast<Transform>().ToList().ConvertAll(t => t.gameObject);
    3.  
    This is what I get for working on art all day, a desire to solve coding problems, regardless of how unimportant they are!
     
    Last edited: Jul 6, 2012
    AMVALOR-LAVAL likes this.
  9. eduardo-pons

    eduardo-pons

    Joined:
    Mar 31, 2009
    Posts:
    176
    LINQ is faster than using List<> or pure arrays?
     
  10. JohnnyA

    JohnnyA

    Joined:
    Apr 9, 2010
    Posts:
    5,061
    I only added it so I could cast the elements of the IEnumerable (Transform implements IEunmerable not IEnumerable<Transform>) and keep it as a one liner. I dare say a non LINQ multiline solution will be faster again.

    (Note that none of these things are slow enough to really matter).

    EDIT: Yup old fashion foreach is faster again.

    EDIT2: Interestingly the GetComponent approaches scales better. After around 50 or so children they are faster than the IEnumerable. Interestingly increasing the children even further and the ConvertAll based methods perform better than even the raw foreach methods (some kind of optimisation in the MSDN code?)
     
    Last edited: Jul 6, 2012
  11. DDMiller

    DDMiller

    Joined:
    Oct 12, 2015
    Posts:
    1
    This is brilliantly simple. Thanks for sharing!
     
  12. Duffer123

    Duffer123

    Joined:
    May 24, 2015
    Posts:
    1,218
    @KelsoMRK ,

    Does that last bit of code just list the children (and not grandchildren etc.) of the gameobject in question?
     
  13. KelsoMRK

    KelsoMRK

    Joined:
    Jul 18, 2010
    Posts:
    5,539
    I believe it's just the first generation of children - that would depend on Transform's implementation of GetEnumerator which I don't remember off the top of my head.
     
  14. passerbycmc

    passerbycmc

    Joined:
    Feb 12, 2015
    Posts:
    1,741
    Why did this devolve into lets do it the craziest way we know possible thread. Im assuming if you want a array of a objects children you are likely just going to loop it. So who not just loop over the transform when you need them, or just grab its Enumerator with GetEnumerator and use it later.

    If you really wanted to convert it to a list or something that acts more list like in 1 line, i would just write a extension method.

    Code (CSharp):
    1. using System.Collections.Generic;
    2. using UnityEngine;
    3.  
    4. public static class CollectionUtils {
    5.     public static IEnumerable<Transform> GetChildren(this Transform transform) {
    6.         var enumerator = transform.GetEnumerator();
    7.         while (enumerator.MoveNext())
    8.             yield return (Transform)enumerator.Current;
    9.     }
    10. }
    11.  
     
    Last edited: Apr 8, 2017
  15. JohnnyA

    JohnnyA

    Joined:
    Apr 9, 2010
    Posts:
    5,061
    The question asked about getting a GameObject, so you still haven't done the (relatively) expensive bit which is retrieving the GameObject. If the collection is large or this operations gets called a lot then this could be an issue.

    For context looping through transforms or using GetEnumerator and then calling transform.gameObject is around 5 times slower than iterating a List of GameObjects (and around 20-50 times slower than iterating an array of GameObjects)*.

    It also causes a small amount of heap allocation each time it is used, 320 bytes regardless of child count. This can add up if its used per frame across multiple objects*.

    @KelsoMRK's solution was a practical solution which enables the list to be cached, it could be optimised to an array if required. The rest was just some programmers having fun, back in 2012 programmers were allowed to have fun here :p

    - - -
    * Exact numbers will vary heavily based on child size, platform, etc.