2
\$\begingroup\$

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?

\$\endgroup\$
1
\$\begingroup\$

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;
\$\endgroup\$
  • \$\begingroup\$ OP wants to get the objects that belongs to a "specific scene". This code piece returns all GameObjects in the game, regardless of the scene they belong. \$\endgroup\$ – S. Tarık Çetin Jul 27 '16 at 17:06
  • \$\begingroup\$ As far as I know the object in a previous scene are deleted when a new scene is loaded. This happen in my project to when I switch from main menù scene to the core scene I have no more the previous objects \$\endgroup\$ – Leggy7 Jul 27 '16 at 17:08
  • \$\begingroup\$ Indeed I Have like 4 or more scenes open at a time; start, Menu, Debug, Background demo and high scores..... I want to be able to hide each of them as I want. \$\endgroup\$ – user2888973 Jul 27 '16 at 17:09
  • \$\begingroup\$ @Leggy7 Not necessarily, if you specify LoadSceneMode.Additive parameter in the loading method, the existing scenes will remain untouched, while the new one gets loaded "additively". \$\endgroup\$ – S. Tarık Çetin Jul 27 '16 at 17:10
  • \$\begingroup\$ @Leggy7 DontDestroyOnLoad(this) during start or awake; will also preserve objects across loads. That is how we transfer data across levels most of the time \$\endgroup\$ – user2888973 Jul 27 '16 at 17:17
1
\$\begingroup\$

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.

\$\endgroup\$
  • \$\begingroup\$ I see your point... Make a list of object loaded from scene one..... make a list of objects from scene one and 2 and delete those from scene one. Load scene 3 and delete the ones from scene 1 and 2 ..... etc.... is there no other way? \$\endgroup\$ – user2888973 Jul 27 '16 at 16:59
  • \$\begingroup\$ @user2888973 Yes, you got it right. This is the quickest way I am aware of to solve this situation. \$\endgroup\$ – S. Tarık Çetin Jul 27 '16 at 17:02
0
\$\begingroup\$

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.

\$\endgroup\$
  • 1
    \$\begingroup\$ Careful when keeping these result lists though, you might cause unintended memory "leaks". \$\endgroup\$ – wondra Jul 27 '16 at 21:18
  • \$\begingroup\$ Thanks for the reminder; you are right; I forgot garbage collection cannot clean up as long as this list exists. when I unload a Scene. Good call \$\endgroup\$ – user2888973 Jul 28 '16 at 8:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.