How do I use GameObject.Find("") to find an inactive object.

I noticed that GameObject.Find cannot find an object that is set inactive. Is there another method I could use?

Nope. Not really another way directly.
You could have an active parent that is an empty gameobject and find that gameobject, then use FindChild or GetChild.
Or you could find an object that has a varaible reference to the gameobject you really want to find, but otherwise, you can’t find inactive objects with GameObject.Find.

If you’re in need of finding disabled objects directly, or any objects really without a direct interaction like a collision, you should have some sort of manager for those object types (a singleton possibly) that you can reference and just have the manager deal with it.

GameObject.Find, FindGameObjectsWithTag, and other functions that search the entire scene are very slow and I’ve only ever used them when quickly prototyping an idea. If every GameObject of a given type registers themselves to a list within a manager script, then removes themselves when they die (or even just letting the manager handle those things itself), then you’ll find things far easier to deal with later.

2 Likes

Object pooling is the best suitable solution for you!

Object pooling is designed for reusing objects over and over. Generally if you have say, 20 bullet objects. You fire a few, then return them back to the “pool” to use again without destroying or having to instantiate new ones. If OP is trying to find a single object, object pooling would serve no purpose.

4 Likes

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 the Start function. Why do you need to find an inactive object? Why are you even de-activating it in the first place?

There is a nasty way of doing it within the editor - it’s handy for running custom editor tools (e.g. I used this in the past for building sprite atlases in EZGUI).

    Transform[] GetAllDisabledSceneObjects()
    {
        var allTransforms = Resources.FindObjectsOfTypeAll(typeof(Transform));
        var previousSelection = Selection.objects;
        Selection.objects = allTransforms.Cast<Transform>()
            .Where(x => x != null )
            .Select(x => x.gameObject)
            .Where(x => x != null && !x.activeInHierarchy)
            .Cast<UnityEngine.Object>().ToArray();
       
        var selectedTransforms = Selection.GetTransforms( SelectionMode.Editable | SelectionMode.ExcludePrefab);
        Selection.objects = previousSelection;
      
        return selectedTransforms;
    }

Assuming you place your inactive object inside a parent, then you can place a script on the parent with something like

transform.GetComponentInChildren<YourType>(true); // returns first child with component (inactive included)
transform.GetComponentsInChildren<YourType>(true); // returns array of all children that have the component (inactive included).

this code assumes that your children objects have a ‘YourType’ component (script) attached to them.
Note, if your parent object has the same component (in this case YourType), GetComponentsInChildren() will return the parent as well.

2 Likes

There is a way to find inactive gameobjects in a scene.

First get a list of root objects for the scene:

Scene scene = SceneManager.GetActiveScene();
var game_objects = new List<GameObject>();
scene.GetRootGameObjects(game_objects);

From there you can recursively iterate over the children of all GameObjects in the list.

5 Likes

Here is a generic method that searches through all hierarchy for the first active/inactive object of Type:

public static T FindObjectOfTypeEvenIfInactive<T>() where T : MonoBehaviour
{
   return Resources.FindObjectsOfTypeAll<Transform>()
      .Select(t => t.GetComponent<T>())
      .FirstOrDefault(c => c != null);
}

Example:

var mouseDummyController = FindObjectOfTypeEvenIfInactive<MouseDummyController>();

But this is the Unity Forums. Any of the following are allowed for any Q:

o Use an object pool

o Use Design Patterns. Remember singletons should be used [always] / [never].

o Rewrite your code to cache everything (which would solve the problem here, which means you must give non-helpful examples of component caching.)

o Use the LINQ library. Also insist Unity update to the most recently proposed version of C# and .NET.

3 Likes

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. Note that this only works if the object doesn’t have any child objects, since then it tries to search the child objects. But if the inactive object is at the bottom of a path with no child objects underneath, then it’ll return that object even if it’s inactive.

Hmmm…“can’t have child objects” is a serious limitation (and it feels a little like a bug). Plus, if you already know the parent and the path, it’s easier to use transform.Find, as in: animalParent.Find(“cow”). That’s what the second reply from Brathnann suggests. It works on inactive objects (both are named “Find”, but they are 2 completely different functions).

Using the path functionality of GameObject.Find is useful for editor code where storing references isn’t possible (storing paths in EditorPrefs.SetString to bookmark objects between editor sessions), so I ran into this problem but none of the above approaches work well for my use case.

(Looks like they fixed the inconsistency HonoraryBob mentioned – now GameObject.Find never returns inactive objects.)

With a few helper functions, here’s my FindObjectWithScenePath. Unlike GameObject.Find, it only accepts a scene path. It needs work to support multiple scenes.

using System.Linq;
using UnityEngine.SceneManagement;
...
//
// Good for editor code, but not suitable for runtime.
//

public static GameObject FindRootObjectWithName(string name) {
    return SceneManager.GetActiveScene()
        .GetRootGameObjects()
        .Where(obj => obj.name == name)
        .FirstOrDefault();
}
// Searches children, not descendants.
public static Transform FindChildWithName(Transform parent, string query) {
    for (int i = 0; i < parent.transform.childCount; ++i) {
        var t = parent.transform.GetChild(i);
        if (t.name == query) {
            return t;
        }
    }
    return null;
}
// Like GameObject.Find when using paths, but includes inactive.
// Example: FindObjectWithScenePath("/Geometry/building01/floor02")
public static GameObject FindObjectWithScenePath(string path) {
    Debug.Assert(!string.IsNullOrWhiteSpace(path), "Must pass valid name");
    Debug.Assert(path[0] == '/', "Must pass scene path (starting with /)");
    path = path.Substring(1);
    var names = path.Split('/');
    if (names.Length == 0) {
        Debug.Assert(false, "Path is invalid");
        return null;
    }
    var go = FindRootObjectWithName(names[0]);
    if (go == null) {
        return null;
    }
    var current = go.transform;
    foreach (var query in names.Skip(1)) {
        current = FindChildWithName(current, query);
        if (current == null) {
            return null;
        }
    }
    return current.gameObject;
}
 public T GetComponentType<T>(string name, string parent) where T : Component
    {
        T[] col = GameObject.Find(parent).GetComponentsInChildren<T>(true);
        foreach (var item in col)
        {
            if (item.name == name)
            {
                return item;
            }
        }
        return null;
    }

Remember the first rule of GameObject.Find():

Do not use GameObject.Find();

More information: Regarding GameObject.Find ¡ UnityTipsRedux

More information: Why cant i find the other objects? - Unity Engine - Unity Discussions

In general, DO NOT use Find-like or GetComponent/AddComponent-like methods unless there truly is no other way, eg, dynamic runtime discovery of arbitrary objects. These mechanisms are for extremely-advanced use ONLY.
If something is built into your scene or prefab, make a script and drag the reference(s) in. That will let you experience the highest rate of The Unity Way™ success of accessing things in your game.

Keep in mind that using GetComponent() and its kin (in Children, in Parent, plural, etc) to try and tease out Components at runtime is definitely deep into super-duper-uber-crazy-Ninja advanced stuff.

This sort of coding is to be avoided at all costs unless you know exactly what you are doing.

Botched attempts at using Get- and Find- are responsible for more crashes than useful code, IMNSHO.

If you run into an issue with any of these calls, start with the documentation to understand why.

There is a clear set of extremely-well-defined conditions required for each of these calls to work, as well as definitions of what will and will not be returned.

In the case of collections of Components, the order will NEVER be guaranteed, even if you happen to notice it is always in a particular order on your machine.

It is ALWAYS better to go The Unity Way™ and make dedicated public fields and drag in the references you want.

@VeteranXT , please don’t necro a long-dead post like this.

2 Likes