I have tried:
foreach (Transform child in transform)
{
}
But this just gets all children in the objects transform, I want to get all children in the object, children of the children, children of the children of the children etc…
Transform[] childArray = GetComponentsInChildren<Transform>();
Note that this will return the transform of the current GameObject as well, so you should either remove that or just remember to reference check it so it skips it in an iteration.
Does this work for all children in the entire object or just children of the children?
It’s completely recursive- it’ll return all components of the type specified in this object’s tree. That includes children of children of children of children of children of children, etc…
Is there i way to check for specific tag at the same time?
At the same time? No, you’ll have to iterate over the results. Luckily GetComponentsInChildren is set up in such a way that it isn’t resource-heavy, provided you use the generic version. Just try to avoid using it every single frame, like all other GetComponent calls. Note that it won’t return inactive objects by default, so you’ll have to use a “true” parameter to be sure you’re getting everything.
You can appear to be doing everything at the same time, using Linq though:
List<Transform> childrenWithTag = GetComponentsInChildren<Transform>(true).Where(t => t.tag == "someTag").ToList();
So how would i do it then, I,m current doing this now:
childArray = GetComponentsInChildren<Transform>();
in Start()
and then i cycle though them:
for (int i = 0; i < childArray.Length; i++) {
childArray[i].GetComponent<Rigidbody>().isKinematic = true;
childArray[i].GetComponent<Rigidbody>().detectCollisions = false;
}
So how would i do this in such a way that i would only add objects with a specic tag?
Edited answer to use the “easy” way, with Linq.
List<Transform> childrenWithTag = GetComponentsInChildren<Transform>(true).Where(t => t.tag == "someTag").ToList();
If you don’t want to use Linq’s extension methods though, it’s still easy:
Transform[] childArray = GetComponentsInChildren<Transform>(true);
List<Transform> boneChildren = new List<Transform>();
foreach(Transform child in childArray)
{
if(child.tag == "bone")
boneChildren.Add(child);
}
Or, you can just check during the iteration of whatever you’re wanting to do with the children, so that it skips over them.
Transform[] childArray = GetComponentsInChildren<Transform>(true);
for (int i = 0; i < childArray.Length; i++)
{
if(childArray[i].tag != "bone")
continue;
childArray[i].GetComponent<Rigidbody>().isKinematic = true;
childArray[i].GetComponent<Rigidbody>().detectCollisions = false;
}
There’s also absolutely no rule that you HAVE to grab the Transform components of children. You could also just do this:
Rigidbody[] childArray = GetComponentsInChildren<Rigidbody>(true);
Which may be better if those are all you’re wanting. You’ll still need to iterate over them and tag-check probably, but it won’t include a bunch of children that don’t even have rigidbodies.
OK thanks this has helped me and worked, what i originally was trying to do is start and stop ragdoll physics, if there is a more efficient way then this please tell me :), thanks.
If you’re wanting to go up and down the chain and disable the collision detection, specifically, then your only choice is it iterate over the entire chain like this, yes. The isKinematic = true isn’t necessary though, because they should all already be kinematic, and that shouldn’t change. The only object who’s kinematic status may change should be the very top-most parent, because you don’t have multiple non-kinematic rigidbodies in a hierarchy, ever.
Bunny explains it best, as always.