How to find inactive objects using GameObject.Find(" ") in Unity3D?

Well, using GameObject.Find(...) will never return any inactive objects. As the documentation states:

This function only returns active gameobjects.

Even if you could, you'd want to keep these costly calls to a minimum.

There are "tricks" to finding inactive GameObjects, such as using a Resources.FindObjectsOfTypeAll(Type type) call (though that should be used with extreme caution).

But your best bet is writing your own management code. This can be a simple class holding a list of objects that you might want to find and use at some point. You can put your object into it on first load. Or perhaps add/remove them on becoming active or inactive. Whatever your particular scenario needs.


If you have parent object (just empty object that plays role of a folder) you can find active and inactive objects like this:

this.playButton = MainMenuItems.transform.Find("PlayButton").gameObject;

MainMenuItems - is your parent object.

Please note that Find() is slow method, so consider using references to objects or organize Dictionary collections with gameobjects you need access very often

Good luck!


First of all

In general any usage of Find or it's variants should be avoided.

Actually they are never really required but only a "hot-fix" used to cover an implementation "laziness".

Usually from the beginning storing and passing on required references is always the better approach.

Especially in your case you seem to have a fix amount of objects so you could probably already reference them all in a certain "manager" component and store them in a list or array (them you can get a reference by index) or even a Dictionary<string, GameObject> (then you can also get the according reference by name - you can find an example below).


Workarounds

There are alternative solutions (FindObjectsWithTag, FindObjectsOfType) but it will always be quite expensive (though most of the Find variants are expensive anyway).

You could e.g. also "manually" iterate through all objects in the scene using Scene.GetRootGameObjects

Returns all the root game objects in the Scene.

And then search through them until you find your object. This way you get also inactive GameObject.

public static GameObject Find(string search)
{
    var scene = SceneManager.GetActiveScene();
    var sceneRoots = scene.GetRootGameObjects();

    GameObject result = null;
    foreach(var root in sceneRoots)
    {
        if(root.name.Equals(search)) return root;

        result = FindRecursive(root, search);

        if(result) break;
    }

    return result;
}

private static GameObject FindRecursive(GameObject obj, string search)
{
    GameObject result = null;
    foreach(Transform child in obj.transform)
    {
        if(child.name.Equals(search)) return child.gameObject;

        result = FindRecursive (child.gameObject, search);

        if(result) break;
    }

    return result;
}

But ofcourse this should be strongly avoided and the usage of such deep searches reduced to a minimum!


What I would do

Another way - in my eyes the best approach here - could be to have a certain component attached to all your objects and actually store all the references once as said before in a dictionary like e.g.

public class FindAble : MonoBehaviour
{
    private static readonly Dictionary<string, GameObject> _findAbles = new Dictionary<string, GameObject>();

    public static GameObject Find(string search)
    {
        if(!_findAbles.ContainsKey(search)) return null;

        return _findAbles[search];
    }

    private IEnumerator Start()
    {
        // Wait one frame
        // This makes it possible to spawn this object and 
        // assign it a different name before it registers
        // itself in the dictionary
        yield return null;

        if(_findAbles.ContainsKey(name))
        {
            Debug.LogError($"Another object with name /"{name}/" is already registered!", this);
            yield break;
        }

        _findAbles.Add(name, gameObject);
    }

    private void OnDestroy ()
    {
        if(_findAbles.ContainsKey(name))
        {
            _findAbles.Remove(name);
        }

        // Optionally clean up and remove entries that are invalid
        _findAbles = _findAbles.Where(kvp => kvp.Value).ToDictionary(kvp => kvp.Key, kvp => kvp.Value);
    }
}

and then use it like

var obj = FindAble.Find("SomeName");
if(obj)
{
    // ...
}

Also for this the component would need to be enabled at least once so Start is called.

Again an alternative would be to have instead a

public void Initialize(string newName)
{
    if(_findAbles.ContainsKey(name))
    {
        Debug.LogError($"Another object with name /"{name}/" is already registered!", this);
        return;
    }

    name = newName;

    _findAbles.Add(name, gameObject);
}

which you could call also after e.g. spawning an inactive object.


You can use Predicates. Just get the gameObjects and check them whith a Predicate as below:

public List<GameObject> FindInactiveGameObjects()
{
    GameObject[] all = GameObject.FindObjectsOfType<GameObject> ();//Get all of them in the scene
    List<GameObject> objs = new List<GameObject> ();
    foreach(GameObject obj in all) //Create a list 
    {
        objs.Add(obj);
    }
    Predicate inactiveFinder = new Predicate((GameObject go) => {return !go.activeInHierarchy;});//Create the Finder
    List<GameObject> results = objs.FindAll (inactiveFinder);//And find inactive ones
    return results;
}

and don't forget using System; using System.Collections.Generic;


In the years since this question was asked, Unity put in the exact thing you need. At least, the exact thing I needed. Posting here for future peoples.

To find an object of a certain type whether it's on an active or inactive GameObject, you can use FindObjectsOfType<T>(true): https://docs.unity3d.com/ScriptReference/Object.FindObjectsOfType.html

Objects attached to inactive GameObjects are only included if inactiveObjects is set to true.

Therefore, just use it like you regularly would, but also pass in true.

The following code requires System.Linq:

List<SpriteRenderer> onlyActive = GameObject.FindObjectsOfType<SpriteRenderer>().ToList();

List<SpriteRenderer> activeAndInactive = GameObject.FindObjectsOfType<SpriteRenderer>(true).ToList();

List<SpriteRenderer> onlyInactive = GameObject.FindObjectsOfType<SpriteRenderer>(true).ToList()
    .FindAll(sr => !sr.gameObject.activeInHierarchy);

The first list includes only SpriteRenderers on active GameObjects, the second includes both those on active and inactive GameObjects, and the third uses System.Linq to only include those on inactive GameObjects.


Comments

  1. Maximiliano

    • 2021/5/30

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

  2. Mercier

    • 2015/7/9

    You could e.g. also "manually" iterate through all objects in the scene using Scene.GetRootGameObjects. Returns all the root game objects in the Scene. And then search through them until you find your object. This way you get also inactive GameObject. public static GameObject Find(string search){ var scene = SceneManager.GetActiveScene(); var sceneRoots = scene.GetRootGameObjects(); GameObject result = null; foreach(var root in sceneRoots) { if(root.name.

  3. Bodie

    • 2017/2/5

    Once an object is inactive, you can't find it. However you shouldn't be using GameObject.Find at all as it is very slow. I ONLY use it in 

  4. Braylen

    • 2017/2/22

    If you have parent object (just empty object that plays role of a folder) you can find active and inactive objects like this: this.playButton = MainMenuItems.transform.Find('PlayButton').gameObject; MainMenuItems - is your parent object. Please note that Find() is slow method, so consider using references to objects or organize Dictionary collections with gameobjects you need access very often. Good luck!

  5. Patel

    • 2020/12/30

    Well, using GameObject.Find() will never return any inactive objects. As the documentation states: This function only returns active 

  6. Ezequiel

    • 2015/11/26

    In case someone comes across this page via an internet search for this common problem: the above answers ignore one specific case in which it is possible to use Find () to get an inactive object if (and only if) you give Find () the full path to a specific gameobject so it doesn't need to do an actual search (e.g. "MyStuff/TheseGuys/ThisSpecificGuy" rather than just "ThisSpecificGuy") I've found this through trial and error.

  7. Nikolas

    • 2019/8/1

    1 - Store inactive game objects in an array if you need to reactivate them afterwards (only applies to game objects inactivated at runtime). 2 - Do not 

  8. Braydon

    • 2020/11/23

    You could e.g. also "manually" iterate through all objects in the scene using Scene.GetRootGameObjects. Returns all the root game objects in the Scene. And then search through them until you find your object. This way you get also inactive GameObject.

  9. Phoenix

    • 2015/4/11

    3 Answers · You can start with the object active, so the script can find and deactivate it, at start. But, then it has a reference to track. · You can create a 

  10. Harvey

    • 2018/5/25

    This is a method for getting a reference to an initially inactive object that avoids the overhead of the Find() type functions: private GameObject myObject; void Start() { myObject = (GameObject)Instantiate(Resources.Load("MyObject")); } Your inactive objects must exist in a folder named "Resources" or within a sub-folder of it:

  11. Johnny

    • 2015/4/23

    GameObject.Find "This function only returns active gameobjects." You can reference inactive objects by using drag'n'drop in the inspector, or by finding 

  12. Azariah

    • 2017/7/27

    Objects attached to inactive GameObjects are only included if inactiveObjects is set to true. Use Resources.FindObjectsOfTypeAll to avoid these limitations. In Editor, this searches the Scene view by default. If you want to find an object in the Prefab stage, see the StageUtility APIs. Note: This function is very slow. It is not recommended to use this function every frame.

  13. Kenneth

    • 2015/1/25

    I use GameObject.Find() in Unity for things like enabling or fading in/out a menu or to grab an object reference via code to store for later 

  14. Jaxon

    • 2015/6/11

    Finds a GameObject by name and returns it. This function only returns active GameObjects. If no GameObject with name can be found, null is returned. If name contains a '/' character, it traverses the hierarchy like a path name. For performance reasons, it is recommended to not use this function every frame.

  15. Hasani

    • 2017/4/21

    Objects attached to inactive GameObjects are only included if If you want to find an object in the Prefab stage, see the StageUtility APIs.

  16. Carson

    • 2017/2/20

    유니티에서 Gameobject.Find(string name) 함수를 사용하면, 해당 name과 일치하는 오브젝트를 찾아줍니다. 무척 편리한 기능이지만, 

Comments are closed.

Recent Posts