Find GameObject in another loaded scene

How do I find or reference a GameObject loaded in another scene?

I’ve tried with GameObject.Find() and Scene.GetSceneByName("myScene").GetRootGameObjects(), but they both failed, one because it seemingly doesn’t recognize objects outside its current scene and the other because it only returns an empty array.

Edit: the scene was loaded additively

1 Like

When you switch scene all objects in that first scene will be deleted (unless they are set as DoNotDestroy).
Also you can load a scene in Additive mode, that will keep objects until you unload that scene.

Instead of using Scene.GetSceneByName, why not use one of the overloads for SceneManager.LoadScene, which returns a Scene. For example:

var parameters = new LoadSceneParameters(LoadSceneMode.Additive);
var scene = SceneManager.LoadScene("MyAdditiveScene", parameters);
        
foreach (var obj in scene.GetRootGameObjects())
{
     Debug.Log(obj.name);
}

I don’t know if this will change anything but it seems like it would work.

Maybe these will help. Though be cautious, these are heavy functions. Don’t use them in Update() etc. Cache their results.

Usage:

var yourComp = FindComponentUtils.FindComponentInAllLoadedScenes<YourComp>(includeInactive: true);

Source:

using System.Collections.Generic;
using System.Linq;

public static class FindComponentUtils
{
    /// <summary>
    /// Returns a Component of type T in all loaded scenes.
    /// Be aware that this may also return an object which is scheduled for destruction at the end of the current frame.
    /// Be double aware that this will NOT return any object marked as "DontDestroyOnLoad" since those are moved to a
    /// unique scene which is not accessible during runtime.
    /// See: https://gamedev.stackexchange.com/questions/140014/how-can-i-get-all-dontdestroyonload-gameobjects
    /// </summary>
    /// <param name="path"></param>
    /// <param name="scenePredicate">Use this to exclude scenes from being searched.</param>
    /// <returns></returns>
    public static T FindComponentInAllLoadedScenes<T>(bool includeInactive, System.Predicate<UnityEngine.SceneManagement.Scene> scenePredicate = null)
    {
        var components = FindComponentsInAllLoadedScenes<T>(includeInactive, scenePredicate);
        if (components.Count > 0)
        {
            return components[0];
        }

        return default(T);
    }

    /// <summary>
    /// Returns all Components of type T in all loaded scenes.
    /// Be aware that this may also return objects which are scheduled for destruction at the end of the current frame.
    /// Be double aware that this will NOT return any objects marked as "DontDestroyOnLoad" since those are moved to a
    /// unique scene which is not accessible during runtime.
    /// See: https://gamedev.stackexchange.com/questions/140014/how-can-i-get-all-dontdestroyonload-gameobjects
    /// </summary>
    /// <param name="path"></param>
    /// <param name="scenePredicate">Use this to exclude scenes from being searched.</param>
    /// <returns></returns>
    public static List<T> FindComponentsInAllLoadedScenes<T>(bool includeInactive, System.Predicate<UnityEngine.SceneManagement.Scene> scenePredicate = null)
    {
        // TODO: For Unity2020+ we could use Object.FindObjectsOfType with includeInactive = true instead.
        UnityEngine.SceneManagement.Scene[] scenes = new UnityEngine.SceneManagement.Scene[UnityEngine.SceneManagement.SceneManager.sceneCount];
        for (int i = 0; i < UnityEngine.SceneManagement.SceneManager.sceneCount; ++i)
        {
            var scene = UnityEngine.SceneManagement.SceneManager.GetSceneAt(i);
            if (scenePredicate == null || scenePredicate(scene))
            {
                scenes *= UnityEngine.SceneManagement.SceneManager.GetSceneAt(i);*

}
}

return FindComponentsInScenes(includeInactive, scenes);
}

public static List FindComponentsInScenes(bool includeInactive, params UnityEngine.SceneManagement.Scene[] scenes)
{
try
{
return scenes
.Where(s => s.IsValid())
.SelectMany(s => s.GetRootGameObjects())
.Where(g => includeInactive || g.activeInHierarchy)
.SelectMany(g => g.GetComponentsInChildren(includeInactive))
.ToList();
}
catch (System.Exception)
{
return new List();
}
}
}