How to find Inactive GameObject

I Have number of objects within the scene that conform to the naming convention:

male_portrait_

Where n is the number of that piece of portrait geometry. When the player clicks on a collider around the portraits, I am activating the next portrait and deactivating the current.

Given that only one can be shown at a time, I've been deactivating all but the first and then in code I was using GameObject.Find("/male_portrait_"), but I was surprised to find that this did not find inactive objects.

I was wondering if there was a way of finding inactive objects?

NOTE: It occurs to me now that I could have turned the mesh renderer and toggle this state in code as the player clicks and still be able to find the objects as I tried to above.

NOTE: my solution was to fix my code so that the objects were all active and I then deactivated the ones that should be hidden.

I'll post solution(s) separately.

I agree it is rather confusing. I expect I can FIND an inactive GameObject

Okay, so I have two solutions:

Solution 1 I left everything active, discovered all the items programatically and turned off the ones I didn't need.

Solution 2 I could hide the mesh renderer in the editor and discover the objects as above.

The confusing thing for me is that within the editor I can drag an inactive object onto the member variable of another script, thereby linking that inactive instance to that script, but I cannot do the same programmatically.

Recursive for the win!

The idea here is using either a non-ideal way of getting all root GameObjects or Tagged objects, as a place where to begin finding. Specially on the first way, this should be slower than regular GameObject.Find, but it will go through inactive objects.

	static public GameObject GameObjectHardFind (string str) {
		GameObject result = null;
		foreach ( GameObject root in GameObject.FindObjectsOfType(typeof(Transform)) ) {
			if (root.transform.parent == null) { // means it's a root GO
				result = GameObjectHardFind(root, str, 0);
				if (result != null) break;
			}
		}
		return result;
	}
	static public GameObject GameObjectHardFind (string str, string tag) {
		GameObject result = null;
		foreach ( GameObject parent in GameObject.FindGameObjectsWithTag(tag) ) {
			result = GameObjectHardFind(parent, str, 0);
			if (result != null) break;
		}
		return result;
	}
	static private GameObject GameObjectHardFind (GameObject item, string str, int index) {
		if (index == 0 && item.name == str) return item;
		if (index < item.transform.childCount) {
			GameObject result = GameObjectHardFind(item.transform.GetChild(index).gameObject, str, 0);
			if (result == null) {
				return GameObjectHardFind(item, str, ++index);
			} else {
				return result;
			}
		}
		return null;
	}

Keep in mind this is compatible with Unity 4 (just tested it on beta 7) but should still be avoided and it is even more unnecessary, due to how U4 now handles active and inactive game objects.

If I get what your saying. You want to disable a object and enable the rest. use SetActiveRecursively if true it will enable the item/activate and that object children aswell. if false it will deactive the object and it's children.

If you want to only disable one part of the object use active.

Heres an example. C#

public GameObject currentlyenabled = GameObject.FindWithTag("enabled");
public GameObject currentlydisabled = GameObject.FindWithTag("disabled");

//After your collision script enter this
currentlyenabled.SetActiveRecursively(false);
currentlydisabled.SetActiveRecursibely(true);

JavaScript

var currentlyenabled = GameObject.FindWithTag ("enabled");
var currentlydisabled = GameObject.FindWithTag ("disabled");

//After your collision script enter this
currentlyenabled.SetActiveRecursively(false);
currentlydisabled.SetActiveRecursibely(true);

Using the tags keep it a bit tidy compared to having multiple game objects going on and off just tag the one enabled with "enabled" and all the ones that are disabled currently "disabled".

If your asking how you can find and turn something on/off that should work. If your asking to find something inactive and access scripts from I am fairly sure you cannot do that, but what I would do in that case is turn that objects render off.

I am a bit stumped on what your asking.

Peace,

EDIT: Did you test it with the tag method that I posted before instead of just using Gameobject.Find ? If that does not work another method would be to make a Gameobject variabled in which you then manually put what object it is into the inspector and then SetActiveRecursively it (this will work).

Example C#:

public GameObject male_portrait;

male_portrait.SetActiveRecursively(true);

Example Java:

var male_portrait : Gameobject;

male_portrait.SetActiveRecursively(true);

Can set up an array at the start with links to them all. Then you never need to run a Find while running, so no worries about inactive. That also puts all the naming stuff in one place.

public GameObject[] Portrait;
// maybe set size in the inspector and drag all in, or:

void initPortraits() {
  Portrait = new GameObject[10];
  string pBase = "male_portrait_";
  for(int i-0;i<10;i++) {
    Portrait *= GameObject.Find(pBase+i); // Ex: male_portrait_0*

Portrait*.active=false;*
}
}
The regular code can now say things like: Portrait[curPort].active=false; curPort++; Portrait[curPort].active=true;

Okay. A little late but I hope my answer could be of service to those who’re still facing this apparently age-old conundrum.

My original problem when I countered this was I had an Event Trigger attached to a Text in the UI that catches pointer downs. So when you click on the Text, something happens. The problem is, the user might click the Text more than once, leading to a series of problems since the trigger is tied to an InvokeRepating() method. So to solve this, I have had to catch the pointer down event only once. My chosen solution was to disable the Text Game Object after being pressed and just activate it later again when I need it to be. The problem with this is, as you’ve guessed, we can’t find a disabled Game Object via its tag.

My solution? Find its parent and access it from there. This was the code the used:

GameObject.FindGameObjectWithTag ("CanvasTag").transform.GetChild(5).gameObject.SetActive(true);

Where CanvasTag is the tag of the parent and 5 is the position of the child from the parent (starting with 0).

I got the inspiration to this answer from Chris333 here.

Hope this helps!

I had the same problem with cameras which had to be inactive at the start and I wanted a decent way to retrieve them afterwards.

Basically what I did is make an empty (!active!) gameobject with a standard name for which I can search, then search for that gameobject and retrieve its components. So if it is an option to put all inactive objects you want to retrieve in a parent object, this might be a way to go.

void Start(){
	GameObject cameras = GameObject.Find("Cameras");
	cams = cameras.GetComponentsInChildren<Camera>(true);
	front = FindCam("FrontCamera");
	side = FindCam("SideCamera");
	perspective = FindCam("Perspective");

---- FindCam just for being complete ----

private Camera FindCam(string name){
	foreach(Camera c in cams){
		if(c.name == name){
			return c;
		}
	}
	return null;
}

Check out the post I added here:
My Solution

This fixed the problem for me.

This will find any transform active or inactive by name

public function GetTransform(tfName : String, _parent : Transform) : Transform
{
for (var _transform : Transform in _parent.GetComponentsInChildren(Transform) )
{
if (_transform.name == tfName)
return _transform;
}
return null;
}

I use next trick. Create empty game object with name example “ContainerGUIPause” and put my inactive gameobject with name “guipausemenu” as child “ContainerGUIPause”.
And use code
GameObject.Find(“ContainerGUIPause”).transform.FindChild(“guipausemenu”);

Enjoy)

If you use Unity 4.5x after version
you can use this code, In my case this is helpful to me,
if ‘activeInHierarchy’ has compile error, change to ‘activeSelf’;

Transform[] transforms = obj.GetComponentsInChildren<Transform>(true);//FindObjectsOfType<Transform>(); //obj.GetComponentsInChildren<Transform>();
		
		foreach(Transform tr in transforms)
		{
			if(tr.parent != null)
				Debug.Log(tr.gameObject.activeInHierarchy.ToString()+":"+tr.name+":"+tr.parent.name);
			else
				Debug.Log(tr.gameObject.activeInHierarchy.ToString()+":"+tr.name+":::");
		}

The way i do this for complex GUI panels which have many controls on them is the following

Create a gui delegate component and place it on the root panel where you have your gui controls

void Awake()

  1. Activate all child game objects
    bool state = dg_VLGUIUtility.SetAllChildrenActive(gameObject);

       public static bool[] SetAllChildrenActive(GameObject go)
       {
           List<bool> state = new List<bool>();
    
           Transform[] transforms = go.GetComponentsInChildren<Transform>(true);
    
           foreach (Transform t in transforms)
           {
               state.Add(t.gameObject.activeSelf);
               t.gameObject.SetActive(true);
           }
    
           return state.ToArray();
       }
    
  2. Reference the controls using GameObject.Find(…

  3. Set the gameobjects back to their original state before reference

    dg_VLGUIUtility.SetAllChildrenState(gameObject, state);

    public static void SetAllChildrenState(GameObject go, bool state)
    {
    Transform transforms = go.GetComponentsInChildren(true);

       for(int i=0; i<transforms.Length; i++)
           transforms_.gameObject.SetActive(state*);*_
    

}

Three years later…

I would just keep the GameObject enabled and then disable the components on the GameObject.

Example:

GetComponent().enabled = false;
GetComponent().enabled = false;

So then after when you want the GameObject to be found, you will do these but .enabled = true;

That’s my solution which seems to work pretty well and short coding involved.

I accidentally found a simple way to do this. If you want to find “Text” in Canvas, you can do

GameObject text = GameObject.Find(“Canvas”).transform.FindChild(“Text”).gameObject;

When you set an object active false, do not setActive(false) the original object. Instantiate a clone from that object and use that object.

GameObject Anim;

Anim = GameObject.Find ("Anim");
			GameObject Clone = Instantiate (Anim,transform.position,Quaternion.identity) as GameObject;
			Clone.SetActive(true);
			Clone.GetComponent<Animator>().enabled = true;
			AnimClone = Clone;
			Invoke("ScoreCounter",5);

var obj = Resources.FindObjectsOfTypeAll().Where(x => x.name == “Test33”).First();