getting the bounds of the group of objects

i am trying to get the center of the group of objects, so that i can center the camera to that group and have all subobjects
in the screen.

here is the code i am using:

var bound : Bounds= new Bounds(Vector3.zero,Vector3.zero);
var Colliders = target.GetComponentsInChildren(Collider);
	
for(var collider : Collider in Colliders){
	if(collider.tag!="group" || collider.tag!="microlabel"){
		bound.Encapsulate(collider.bounds);
	}
}
	
Debug.Log("center: " + bound.center.ToString() + " size: " + bound.size.ToString());
	
var sphere : GameObject=GameObject.CreatePrimitive(PrimitiveType.Sphere);
	
sphere.transform.position=bound.center;
sphere.transform.localScale=Vector3(0.2,0.2,0.2);

this works fine for group of groups of objects, but it does not calculate the group that only holds objects
i have offset by the y axis, what to do? maybe i am missing something? how to calculate this type of thing
properly?

thanks

ok i guess that i should use the mesh.bounds instead of collider bounds. it is harder to get those i think. can somebody help me replace collider bounds with mesh.bounds in the code i provided. any help appreciated!

using renderer.bounds instead of collider.bounds gives same result
also when i click on the group of object in the hierarchy i gizmo positions correctly in the center of the objects

can somebody help me with this?

i tried this with mesh.Bounds

it gives me 0,0,0 for position no matter what group i choose?!

	//BOUNDS ARE CREATED WITH CENTER AND SIZE
	var bound : Bounds= new Bounds(Vector3.zero,Vector3.zero);
	
	var arr =target.GetComponentsInChildren(Transform);
	
	var children = new Array();
	
	for(i=0;i<arr.length;i++){
	 if(!(arr[i].tag=="group" || arr[i].tag=="microlabel")){		
	 children.Push(arr[i]);		
	 }	
        }
	
	
	for(i=0;i<children.length;i++){
		
	 bound.Encapsulate(children[i].GetComponent(MeshFilter).mesh.bounds);		
	}

i am obviously doing something wrong

i tried also this:

var filters = target.GetComponentsInChildren(MeshFilter);

for(var filter : MeshFilter in filters)
{
    //if members are not tagged group or microlabel since these are just groups
    if(filter.tag!="group" || filter.tag!="microlabel")
    {
        bound.Encapsulate(filter.mesh.bounds);
    }
}

(thanks Ejlersen for this)

but

puting the sphere in the position of the bound does not give me a good result. it seems that all calculated bounds
are in the same position…

var sphere : GameObject=GameObject.CreatePrimitive(PrimitiveType.Sphere);
	sphere.transform.position=bound.center;

although they have different coords, i got them with this line:

Debug.Log("center: " + bound.center.x +" "  + bound.center.y + " " + bound.center.z);

it seems that nothing is working… can somebody verify this?

any ideas?

maybe too late but i needed this so probably is going to be useful for someone.

	Bounds getBounds(GameObject objeto){
		Bounds bounds;
		Renderer childRender;
	    bounds = getRenderBounds(objeto);
		if(bounds.extents.x == 0){
			bounds = new Bounds(objeto.transform.position,Vector3.zero);
			foreach (Transform child in objeto.transform) {
				childRender = child.GetComponent<Renderer>();
				if (childRender) {
	        		bounds.Encapsulate(childRender.bounds);
				}else{
					bounds.Encapsulate(getBounds(child.gameObject));
				}
        	}
		}
		return bounds;
	}
	Bounds getRenderBounds(GameObject objeto){
		Bounds bounds = new  Bounds(Vector3.zero,Vector3.zero);
		Renderer render = objeto.GetComponent<Renderer>();
		if(render!=null){
			return render.bounds;
		}
		return bounds;
	}
9 Likes

Thanks very much.

Great snippet - thanks!

Amazing…

Necro of a necro of a necro, but worth it IMO. This really is a great little piece of code. You could also adapt this to work with colliders a bit faster/more efficiently than renderer bounds, although you’d lose a lot of precision in the process.

I haven’t seen anything around, but part of me is curious if there’s a method in Unity to do exactly this, seeing as how useful it is and that it’s been years since this solution was presented.

Thank you!

Hey this worked better for me

public static Bounds GetBounds(GameObject obj)
{
Bounds bounds = new Bounds();
Renderer[ ] renderers = obj.GetComponentsInChildren<Renderer>();
if (renderers.Length > 0)
{
//Find first enabled renderer to start encapsulate from it
foreach (Renderer renderer in renderers)
{
if (renderer.enabled)
{
bounds = renderer.bounds;
break;
}
}
//Encapsulate for all renderers
foreach (Renderer renderer in renderers)
{
if (renderer.enabled)
{
bounds.Encapsulate(renderer.bounds);
}
}
}
return bounds;
}
7 Likes

Here’s a version that returns bounds of all children in the local space of the parent (I use it for calculating collider for multiple meshes).

static Bounds GetLocalBoundsForObject(GameObject go)
        {
            var referenceTransform = go.transform;
            var b = new Bounds(Vector3.zero, Vector3.zero);
            RecurseEncapsulate(referenceTransform, ref b);
            return b;
                       
            void RecurseEncapsulate(Transform child, ref Bounds bounds)
            {
                var mesh = child.GetComponent<MeshFilter>();
                if (mesh)
                {
                    var lsBounds = mesh.sharedMesh.bounds;
                    var wsMin = child.TransformPoint(lsBounds.center - lsBounds.extents);
                    var wsMax = child.TransformPoint(lsBounds.center + lsBounds.extents);
                    bounds.Encapsulate(referenceTransform.InverseTransformPoint(wsMin));
                    bounds.Encapsulate(referenceTransform.InverseTransformPoint(wsMax));
                }
                foreach (Transform grandChild in child.transform)
                {
                    RecurseEncapsulate(grandChild, ref bounds);
                }
            }
        }
3 Likes

How do we use this, actually? I’m also having a problem with my generated mesh out of bounds…

But my mesh is dynamically generated (clothes and armor) so it changes. How do I call this? Where do I set it?

you don’t need to use bounds to get the center of a group of objects. Just average their transform.positions to get the center.

Tried all of these and did not get a real bounds that wasn’t axis alligned so the easiest way to take each prefab and add my own “bounds” box that I manually scale. That will rotate with the object and be the correct real bounds that can be used for whatever you want (I wanted to hilight the object the user points to).