- Home /
GetComponentsInChildren only returns children if parent has them?
I am trying to selectively turn on and off models based on their name, and I'm running into an issue. My current code is at the bottom.
For context, I have two models, as can be seen in the picture below:
Right now, my code loads grabs the "Chair" name fine, but fails to grab "Table". Instead, it grabs ALL of the children ("Bein" through "Stutze_3"), but not table itself. I know GetComponentsInChildren uses depth first search, but I can't understand why it won't grab table. Any help is appreciated.
var rendererComponents = GetComponentsInChildren<Renderer>(true);
VuMarkTarget vuMarkObj = GetVuMarkObj();
string vuMarkID = GetVuMarkId(vuMarkObj).Trim();
string vuMarkName = null;
if (furnitureDictionary.TryGetValue(vuMarkID, out vuMarkName))
{
Debug.Log("vuMarkID accepted, value = " + vuMarkID);
Debug.Log("vuMarkName is " + vuMarkName);
}
else
{
Debug.Log("vuMarkID rejected, value = " + vuMarkID);
return;
}
// Enable rendering:
foreach (var component in rendererComponents) {
bool loadVariable = vuMarkName.CompareTo(component.name) == 0;
Debug.Log("Component name found = " + component.name);
Debug.Log("loadVariable value = " + loadVariable.ToString());
/* If the component name is equal to the VuMarkID, it will be loaded */
component.enabled = loadVariable;
}
Answer by Bunny83 · Oct 28, 2017 at 02:59 AM
Uhm you look for Renderer components. I'm pretty sure that "Table" doesn't have any renderer component attached.
If you actually want to abstract the enabling / disabling of renderers of certain objects which might consist of several sub objects you may want to use a "managing" script like this which you can add to any "logical object":
public RendererCollection : MonoBehaviour
{
public Renderer[] renderers;
public void SetState(bool aState)
{
foreach(var r in renderers)
r.enabled = aState;
}
public void Disable()
{
SetState(false);
}
public void Enable()
{
SetState(true);
}
}
Now only attach this script to the root objects which represent an actual object and in the inspector you can drag&drop all the child objects this script should manage. From your code you can search for "RendererCollection" instances and use the method(s) to enable / disable all the renderers which belong to this object at once.
Thank you for the reply. I'm fairly new to Unity, so I assumed a renderer component meant an object that could be rendered, and disabling it did exactly that. In your code, what is the purpose of declaring renderers
? Is that implicitly referring to all the children of the object? Lastly, are you saying this script would be attached to "Table"? And by drag&dropping the child objects, is that in the hierarchy (so things like Bein under Table)? Thanks again.
No, renderers will not implicitly reference anything. You are supposed to assign the renderer components which belong to that object yourself. You may need to temporarily lock the inspector to assign multiple objects at once. See this animated gif i made some time ago
The script is ment to be attached to every logical object. So you would attach it to your Table but also to your chair (and maybe other objects as well). The script is ment to abstract / unify the way you can enable / disable one or multiple renderers which belong to the same logical object.
var objects = GetComponentsInChildren<RendererCollection>(true);
//[ ... ]
foreach (var obj in rendererComponents)
{
obj.SetState(obj.name == vu$$anonymous$$arkName);
}
However depending on whats the actual application of this you may consider Instantiating the right prefabs ins$$anonymous$$d of having all those objects in the scene.
Also note that you can set a whole gameobject inactive by using SetActive on a gameobject. This will naturally disable every renderer and script that is attached to the gameobject or any of it's children.
If you want to iterate through all immediate children of a certain object you can actually use a foreach loop like this;
foreach(Transform obj in someGameObject.transform)
{
obj.gameObject.SetActive(obj.name == vu$$anonymous$$arkName);
}
Though keep in $$anonymous$$d that setting a gameobject inactive basically removes it temporarily from the scene. That means the colliders are also gone. Just disabling the renderer component(s) will only disable the visual representation but other components will still work. So if the object has colliders they will still work.
It's difficult to give a clear advice if we don't know the actual application.
Ah, O$$anonymous$$, I understand what you mean now. The application is just supposed to represent the objects using augmented reality, based on a Vu$$anonymous$$ark (which is like a QR code). Right now there are no physics components attached to them, but there may be in the future, so I will certainly keep your last point in $$anonymous$$d. I think I understand what I need to do. I'll test it out and see if I can get everything to behave. I really appreciate the help; thank you.
Your answer
![](https://koobas.hobune.stream/wayback/20220612142010im_/https://answers.unity.com/themes/thub/images/avi.jpg)