Get all objects of Additively loaded Scene? (LoadSceneMode.Additive)

Get all objects of Additively loaded Scene? (LoadSceneMode.Additive)

I learned how to Load and unload scenes in unity. using LoadSceneMode.Additive.
I like to spit up my scenes as much as possible and retain the stuff I need as I go along.
I'd like to be able to find all objects loaded from a specific scene. Obviously Unity knows but I can't find how to get them.
For now, my workaround is to put them in a specifically named empty or have them tagged in a certain way, but that is a workaround.
Is there an easier way?

Solutions/Answers:

Answer 1:

From this answer mixed with your needs, I would proceed in this way:

List<GameObject> FindSceneObjects(string sceneName){
    List<GameObject> objs = new List<GameObject>();
    foreach (GameObject obj in Object.FindObjectsOfType(typeof(GameObject)))
    {
        if(objs.scene.name.CompareTo(sceneName) == 0){
            objs.Add(objs);
        }
    }
    return objs;
}

Or you can compress the for-loop using a linqstatement

var objs = from GameObject go in GameObject.FindObjectsOfType(typeof(GameObject)) where go.scene.name == sceneName select go;

Answer 2:

Cache all objects at the start and detect the changes in the array (or the list).

To elaborate more, have a list like this:

//This list holds all the GameObjects that are currently in the game.
private List<GameObject> _existingObjects = new List<GameObject>();

And call this method at the beginning of the game, and every time a scene is loaded:

//using System.Linq;

public List<GameObject> FindNewGameObjects()
{
    //Get all GameObjects.
    var allObjects = (FindObjectsOfType(typeof(GameObject)) as GameObject[]).ToList();

    //Substract the existing GameObjects from all GameObjects, so the result will be the new ones.
    var result = allObjects.Except(_existingObjects).ToList();

    //Update our list.
    _existingObjects = allObjects;

    //Return the result.
    return result;
}

The return of the FindNewGameObjects() method will be the list of GameObjects that came with the loaded scene.

Note: The code is not tested.

Answer 3:

Unity has a struct named Scene. From Scene you can get all of the root GameObjects of this particular scene.

Note that the code is not tested.

public static class SceneExtensions
{
    public static void GetAllGameObjects(this Scene scene, out List<GameObject> allGameObjects)
    {
        GameObject[] rootGameObjects = scene.GetRootGameObjects();

        allGameObjects = new List<GameObject>(rootGameObjects);

        for (int a = 0; a < rootGameObjects.Length; a++)
        {
            //? This is kind of a hack because you can use recursive or other methods to access children via `Transform - GetChild()`. I haven't tested which method is more efficient.
            Transform[] childrenTransform = rootGameObjects[a].GetComponentsInChildren<Transform>();

            for (int b = 0; b < childrenTransform.Length; b++)
                allGameObjects.Add(childrenTransform[b].gameObject);
        }
    }

    public static GameObject[] GetAllGameObjects(this Scene scene)
    {
        scene.GetAllGameObjects(out List<GameObject> allGameObjects);

        return allGameObjects.ToArray();
    }
}

Then the usual approach is to get scene by build index.

Scene scene = SceneManager.GetSceneByBuildIndex(sceneBuildIndex);

From my own experience, only loaded scenes will give you the correct result when using this method to get a scene. I couldn’t find a way to get a Scene of unloaded SceneAsset at run-time (I would appreciate if someone shared this with me if such thing is achievable).

Then you can proceed to getting all of the GameObjects of that Scene.

GameObject[] sceneGameObjects = scene.GetAllGameObjects();

Answer 4:

My problem got solved. I will put points toward Leggy7 as he gave me the idea to solve my the problem.

The Old procedure is his way of solving it….

List<GameObject> FindSceneObjects_Old(String sceneName)
{
    List<GameObject> objs = new List<GameObject>();
    foreach (GameObject obj in GameObject.FindObjectsOfType(typeof(GameObject)))
    {
        if (obj.scene.name == sceneName)
        {
            objs.Add(obj);
        }
    }

    return objs;
}

This is my way of solving it using LINQ

List<GameObject> FindSceneObjects(String sceneName)
{
    var objs = from GameObject go in GameObject.FindObjectsOfType(typeof(GameObject)) where go.scene.name == sceneName select go;

    return objs.ToList();
} 

Note: Both codes tested and functional

I am aware there is a shorthand for writing LINQ statements but since I have a Background in SQL I am used to this format.

References