Search Unity

EditorScript: How to get all GameObject's in scene?

Discussion in 'Scripting' started by Peter77, Jan 25, 2014.

  1. Peter77

    Peter77

    QA Jesus

    Joined:
    Jun 12, 2013
    Posts:
    6,619
    I'm trying to get all gameobjects, enabled and disabled ones, that are listed in the hierarchy/scene inside the editor from an editor script. I found quite a few results on this issue in unity answers and the forum, but actually none of the answers is working as far as my tests go.

    I found "Object.FindObjectsOfType" and "Object.FindSceneObjectsOfType" which pretty much do what I'm looking for, but both methods find active gameobjects only, but I also need to get inactive ones.

    Another candidate is "Resources.FindObjectsOfTypeAll". This one finds active and inactive gameobjects, but it also returns objects that have been selected in the project window and are actually not part of the current scene (the documentation says its result may contain internal objects). I thought I could detect and filter these non-scene objects from their hideFlags, I hoped these objects have the "HideFlags.HideInHierarchy" bit set or so, but it's not the case.

    Is there any way to get all (enabled and disabled) gameobjects of the current scene only, from an editor script?
     
  2. scabnog

    scabnog

    Joined:
    Jan 30, 2014
    Posts:
    3
    Bump. This seems like something that should be trivially easy to find, but I am also having trouble iterating over inactive gameobjects in the hierarchy. Is there a simple way to get everything in the hierarchy including inactive gameobjects? I don't want the selection to include anything internal or in the project folders. Thanks.
     
  3. HiddenMonk

    HiddenMonk

    Joined:
    Dec 19, 2014
    Posts:
    987
    FernTLG and kk99 like this.
  4. kelnaath

    kelnaath

    Joined:
    Aug 29, 2013
    Posts:
    1
    I was in a similar situation where i needed to find all components of a certain type from all active and inactive gameobjects from a scene.
    The method below returns all root gameobjects be they active or inactive.
    Code (CSharp):
    1. UnityEngine.SceneManagement.SceneManager.GetActiveScene().GetRootGameObjects();
    If you iterate through the list of root gameobjects with HiddenMonk's solution you should be able to retrieve all active and inactive gameobjects.
     
    melsov, Mallux_, Bunny83 and 2 others like this.
  5. Projectile_Entertainment

    Projectile_Entertainment

    Joined:
    Feb 11, 2016
    Posts:
    31
    I'm late to this particular party, but I had this question myself, so for others' sake, here's what I found:

    The docs here: https://docs.unity3d.com/ScriptReference/Resources.FindObjectsOfTypeAll.html have a pretty good method called GetAllObjectsInScene().

    That said, I would personally change it to this:
    private static List<GameObject> GetAllObjectsInScene()
    {
    List<GameObject> objectsInScene = new List<GameObject>();

    foreach (GameObject go in Resources.FindObjectsOfTypeAll(typeof(GameObject)) as GameObject[])
    {
    if (go.hideFlags != HideFlags.None)
    continue;

    if (PrefabUtility.GetPrefabType(go) == PrefabType.Prefab || PrefabUtility.GetPrefabType(go) == PrefabType.ModelPrefab)
    continue;

    objectsInScene.Add(go);
    }
    return objectsInScene;
    }

    Works in editor
    Gets inactive objects
    Doesn't grab hidden objects
    Doesn't grab prefabs
    Doesn't grab transient objects
     
  6. Peter77

    Peter77

    QA Jesus

    Joined:
    Jun 12, 2013
    Posts:
    6,619
    You don't have to use FindObjectOfType in newer Unity versions to get all GameObject's in a Scene anymore. Unity Technologies added the following method:
    https://docs.unity3d.com/ScriptReference/SceneManagement.Scene.GetRootGameObjects.html

    Once you have the scene root GameObjects, you can traverse their hierarchy and collect whatever objects you're interested in. Works in Editor and Runtime.
     
  7. Spellbook

    Spellbook

    Joined:
    May 21, 2015
    Posts:
    30
    Code (CSharp):
    1.  
    2. public static IEnumerable<GameObject> GetAllRootGameObjects()
    3.     {
    4.         for (int i = 0; i < SceneManager.sceneCount; i++)
    5.         {
    6.             GameObject[] rootObjs = SceneManager.GetSceneAt(i).GetRootGameObjects();
    7.             foreach (GameObject obj in rootObjs)
    8.                 yield return obj;
    9.         }
    10.     }
    11.  
    12.     public static IEnumerable<T> FindAllObjectsOfTypeExpensive<T>()
    13.         where T : MonoBehaviour
    14.     {
    15.         foreach (GameObject obj in GetAllRootGameObjects())
    16.         {
    17.             foreach (T child in obj.GetComponentsInChildren<T>(true))
    18.                 yield return child;
    19.         }
    20.     }
    21.  
    The solutions above ignore multiple scenes loaded at the same time and will only find objects in the active scene, or will also pull in Resources like prefabs not in the scene.

    My code will find all components of a type in every loaded scene, even on disabled and nested-disabled objects.

    The only thing it won't find is objects in the magic DontDestroyOnLoad scene, which is gross and confusing on Unity's part.

    Note: This can be a very expensive operation. Calling it regularly (like every Update frame) can break your game.
     
    designleviathan and Remi_Tribia like this.
  8. paresh_unity496

    paresh_unity496

    Joined:
    May 6, 2019
    Posts:
    5
    The solution is simple and sweet.
    just use the following method.

    Code (CSharp):
    1.  
    2.     List<GameObject> GetAllObjectsOnlyInScene()
    3.     {
    4.         List<GameObject> objectsInScene = new List<GameObject>();
    5.  
    6.         foreach (GameObject go in Resources.FindObjectsOfTypeAll(typeof(GameObject)) as GameObject[])
    7.         {
    8.             if (!EditorUtility.IsPersistent(go.transform.root.gameObject) && !(go.hideFlags == HideFlags.NotEditable || go.hideFlags == HideFlags.HideAndDontSave))
    9.                 objectsInScene.Add(go);
    10.         }
    11.  
    12.         return objectsInScene;
    13.     }
    if you need a simple GameObject Array instead of List then convert it by ToArray() methods.
    ex.
    Code (CSharp):
    1.  GameObject[] allObjectTemp = GetAllObjectsOnlyInScene().ToArray();
    https://docs.unity3d.com/ScriptReference/Resources.FindObjectsOfTypeAll.html
     
  9. Darkgaze

    Darkgaze

    Joined:
    Apr 3, 2017
    Posts:
    397
    Just a simpler and easier to read way to do this:

    Code (CSharp):
    1. foreach (GameObject go in Resources.FindObjectsOfTypeAll(typeof(GameObject)) as GameObject[])
    2. ...
    is this

    Code (CSharp):
    1. foreach (var go in Resources.FindObjectsOfTypeAll<GameObject>())
    2. ...
     
  10. Peter77

    Peter77

    QA Jesus

    Joined:
    Jun 12, 2013
    Posts:
    6,619
    Be careful using
    Resources.FindObjectsOfTypeAll
    to find scene objects, because it might return prefabs from the project too. We found out the hard-way, with an issue where our code sometimes picked a prefab in the project instead of an object in the scene.

    A more reliable method to find GameObject's in the hierarchy is
    Object.FindObjectsOfType
    :
    https://docs.unity3d.com/ScriptReference/Object.FindObjectsOfType.html

    In Unity 2020.3 they added the ability to find inactive GameObject's with
    Object.FindObjectsOfType
    , which didn't work before, thus all the workarounds you find in this thread.
     
  11. Darkgaze

    Darkgaze

    Joined:
    Apr 3, 2017
    Posts:
    397
    Yes . I'm aware of that. I was just reducing the previous code with a simpler way.
    I use this function to gather hidden objects that were marked non editable or hidden in the hierarchy and not-unloadable via de hideFlags and impossible to delete from any scene loaded. This is the only way to get those objects, sadly.