unity has the little checkbox, and the scripting property isActive, to turn objects on and off. But what can i do with an object when it’s deactivated?
Can i still find it (or components on it) with functions like GetComponentsInChildren? Can i still set and/or read properties from scripts attached to such objects?
What about if i have joints attached to a deactvated object, will those joints stop doing anything, or will they continue to be linked to, and apply forces to, rigidbodies?
Its my understanding that deactivated object do nothing. They arent rendered, Update methods in scripts are not called. Physics are not simulated. I am not even sure you can call GetComponent on it until you activate it.
One thing I would like to know thow is, if you search for game objects are inactive objects returned?
Consider the GameObjects active state as the on/off switch on your computer. When it is off it will not do anything by itself. You can still do what you want to it; Open it up, see what components it has, move it around. That is if you lnow where you left it. If you dont know where it is finding it can be a bit challenging.
from memory one of the find functions does pickup on deactivated objects… can’t remember which one though, you’d have to check the scripting reference. The approach really should be “don’t lose the references”/“make sure you have a reference before deactivating”
Resources.FindObjectsOfTypeAll(typeof(GameObject)). But it also returns non-scene objects such as prefabs, so you need to check. Sometimes you don’t know ahead of time what GameObjects you need to work with, leaving you only with this option. But if you can get references beforehand as others suggested, that’s the better option.
This is troubling. I think i need a little advice then.
What i’m attempting to do, is to locate a joint which i’ve preconfigured. The joint is a manipulator on a character (think like a hand, or mouth, for grabbing things) and the joint component is attached to a little object that is attached to a bone.
I’ve had a lot of problems “disabling” joints before. In that there is no disable checkbox, and some joint types still do things when not connected to anything. So my solution for disabling it was going to be to disable the little object it’s on, instead. And whenever i want the limb to grab something, enable that object and then attach the thing to the AttachedBody parameter
I was planning to use FindComponentsInChildren() to locate the little manipulators, now i’m not sure what to do I don’t think i can have them starting in an enabled state in order t be found, that nay still cause issues. And are the references even going to be preserved if i disable then re-enable them?
I find the easiest way to figure stuff out like this is to just write a simple test case that shows what you want to see.
Your post made me curious because honestly I had forgotten the nuances of Unity’s policy on reporting inactive objects, so I wrote the enclosed package, which includes the following script.
See the scene for how it is used. Remember, to understand recursion, you must first understand recursion.
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
public class ListChildrenRecursively : MonoBehaviour
{
public Text Output;
void TraverseTransform( int i, Transform tr)
{
i++;
foreach( Transform t in tr)
{
// You could ask other questions here, like "does this have my joint?"
string oneline = new string( '-', i) + t.name +
(t.gameObject.activeSelf ? " (Active)" : " (Inactive)");
if (Output != null)
{
Output.text += oneline + "\n";
}
Debug.Log ( oneline);
TraverseTransform(i, t);
}
}
void Start()
{
TraverseTransform( 0, transform);
}
}
It seems that GetComponentsInChildren will NOT detect components attached to disabled children.
However, myObject.GetComponents WILL work if myObject is disabled.
So its eems that crawling the hierarchy is my only option here. A little more troublesome to write, though i suspect it’s fundamentally identical as far as unity is concerned
Why not have a small script on the main character that you can manually assign disabled joint GameObjects to?
public class Joints : MonoBehaviour {
public GameObject mouth; // <-- Assign to these if the joint is present on the character.
public GameObject leftHand;
public GameObject rightHand; // etc.
}
Then you don’t need to do any searching at runtime.
In one of my more insane moments I started every scene with every object enabled. This meant I could use Find to my hearts content. Then I would disable everything I didn’t need active after that first frame.
I’ve since repented of that methodology. There are plenty of other good ways to get a reference.
Alas, unfortunately this pattern is still in widespread use in the Unity world, especially in the UI sub-world. Nothing quite like working with a single scene containing every possible button, overlay window, popup, scrollbar, pulldown menu, etc., all laid right on top of each other like a massive deck of misshapen index cards and stray lettering.
For lightweight stuff I’m kind of a fan of making prefabs with some type of “adaptor” script at their root. Use the inspector to drag child objects (or assets) into the adaptor script’s public variables, and then anyone can search for the adaptor for a given thing and immediately know where all of its constituent parts are located.
And when I say adaptor scripts, it’s often a script containing no code, just a bunch of public references to as-tightly-typed Unity objects as possible, such as materials, sub-scripts, transforms, etc. F’rinstance:
using UnityEngine;
using System.Collections;
// Adaptor class to go on the root of all WingDingBat Prefabs
public class WingDingBatAdaptor : MonoBehaviour
{
public Texture Wing;
public Transform Ding;
public Material Bat;
}
That way if you can pick up WingDingBats as a player, there would be a WieldWingDingBatController that would know how to let a player use one. But when WingDingBats are being spawned and offered for retrieval around the world, there might be a SpawnWingDingBatController that spins it in space a few feet off the ground, and perhaps the level controller would keep track of those.
While some strict encapsulation people might be shuddering, I’ve found this approach works very nicely in Unity and scales nicely to the size of projects I tend to get involved with, and does not add too much extra hassle overhead.
Thanks; that’s similar to this previous post. @Kiwasi got me wondering what other ideas he had in mind for getting references in the context of Nanako’s original post.
First up focus on dependencies and making each of your scripts actually need as few references as possible :).
After that here are some options for getting references to inactive GameObjects or components.
Use prefabs. Wiring up references between prefab components in the inspector is not that big of a deal. Prefabs will hold references to their children when they are Instantiated.
Keep references when you create an object
Use manager scripts to provide references
Use GetComponentsInChildren. If you know there is only one of the component in the hierarchy, use that. Otherwise you’ll need to check to find the one you want. Pro tip: GetComponentsInChildren is great for finding individual GameObjects
And of course, its always worth considering weather you really need the GameObject to be disabled. Many platforms can handle simply adding the component you need and configuring it at run time.
For the OP’s use case I would suggest something like:
My current favourite for UI is to wire up everything in reverse via reflection. The individual ‘world’ objects have no idea that the UI exists or is watching them. The UI finds its way in with a GameObject reference and the name of the variable it is intended to watch. Thus the UI is not dependent on specific types from the world objects. Its a win-win from a dependency standpoint.
From a performance standpoint I suspect its a pretty expensive way to do things. But so far my games are pretty light weight, I’m not exactly pushing the limits of computing power, so there is no need to sacrifice the flexibility in favour of performance.
I’m still experimenting on the UI stuff, I might change my mind again later.