Search Unity

getting the bounds of the group of objects

Discussion in 'Scripting' started by pretender, Dec 16, 2010.

Thread Status:
Not open for further replies.
  1. pretender

    pretender

    Joined:
    Mar 6, 2010
    Posts:
    865
    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:


    Code (csharp):
    1.    
    2. var bound : Bounds= new Bounds(Vector3.zero,Vector3.zero);
    3. var Colliders = target.GetComponentsInChildren(Collider);
    4.    
    5. for(var collider : Collider in Colliders){
    6.     if(collider.tag!="group" || collider.tag!="microlabel"){
    7.         bound.Encapsulate(collider.bounds);
    8.     }
    9. }
    10.    
    11. Debug.Log("center: " + bound.center.ToString() + " size: " + bound.size.ToString());
    12.    
    13. var sphere : GameObject=GameObject.CreatePrimitive(PrimitiveType.Sphere);
    14.    
    15. sphere.transform.position=bound.center;
    16. sphere.transform.localScale=Vector3(0.2,0.2,0.2);
    17.  
    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
     
    Last edited: Dec 16, 2010
  2. pretender

    pretender

    Joined:
    Mar 6, 2010
    Posts:
    865
    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!
     
  3. pretender

    pretender

    Joined:
    Mar 6, 2010
    Posts:
    865
    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?
     
  4. pretender

    pretender

    Joined:
    Mar 6, 2010
    Posts:
    865
    i tried this with mesh.Bounds

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

    Code (csharp):
    1.     //BOUNDS ARE CREATED WITH CENTER AND SIZE
    2.     var bound : Bounds= new Bounds(Vector3.zero,Vector3.zero);
    3.    
    4.     var arr =target.GetComponentsInChildren(Transform);
    5.    
    6.     var children = new Array();
    7.    
    8.     for(i=0;i<arr.length;i++){
    9.      if(!(arr[i].tag=="group" || arr[i].tag=="microlabel")){       
    10.      children.Push(arr[i]);    
    11.      } 
    12.         }
    13.    
    14.    
    15.     for(i=0;i<children.length;i++){
    16.        
    17.      bound.Encapsulate(children[i].GetComponent(MeshFilter).mesh.bounds);      
    18.     }
    i am obviously doing something wrong
     
  5. pretender

    pretender

    Joined:
    Mar 6, 2010
    Posts:
    865
    i tried also this:

    Code (csharp):
    1. var filters = target.GetComponentsInChildren(MeshFilter);
    2.  
    3. for(var filter : MeshFilter in filters)
    4. {
    5.     //if members are not tagged group or microlabel since these are just groups
    6.     if(filter.tag!="group" || filter.tag!="microlabel")
    7.     {
    8.         bound.Encapsulate(filter.mesh.bounds);
    9.     }
    10. }
    (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...

    Code (csharp):
    1. var sphere : GameObject=GameObject.CreatePrimitive(PrimitiveType.Sphere);
    2.     sphere.transform.position=bound.center;
    although they have different coords, i got them with this line:

    Code (csharp):
    1. Debug.Log("center: " + bound.center.x +" "  + bound.center.y + " " + bound.center.z);
    it seems that nothing is working... can somebody verify this?
     
  6. pretender

    pretender

    Joined:
    Mar 6, 2010
    Posts:
    865
    any ideas?
     
  7. ddfire

    ddfire

    Joined:
    Dec 22, 2010
    Posts:
    53
    maybe too late but i needed this so probably is going to be useful for someone.

    Code (csharp):
    1.     Bounds getBounds(GameObject objeto){
    2.         Bounds bounds;
    3.         Renderer childRender;
    4.         bounds = getRenderBounds(objeto);
    5.         if(bounds.extents.x == 0){
    6.             bounds = new Bounds(objeto.transform.position,Vector3.zero);
    7.             foreach (Transform child in objeto.transform) {
    8.                 childRender = child.GetComponent<Renderer>();
    9.                 if (childRender) {
    10.                     bounds.Encapsulate(childRender.bounds);
    11.                 }else{
    12.                     bounds.Encapsulate(getBounds(child.gameObject));
    13.                 }
    14.             }
    15.         }
    16.         return bounds;
    17.     }

    Code (csharp):
    1.     Bounds getRenderBounds(GameObject objeto){
    2.         Bounds bounds = new  Bounds(Vector3.zero,Vector3.zero);
    3.         Renderer render = objeto.GetComponent<Renderer>();
    4.         if(render!=null){
    5.             return render.bounds;
    6.         }
    7.         return bounds;
    8.     }
     
  8. builtbyrachel

    builtbyrachel

    Joined:
    Jun 14, 2012
    Posts:
    1
    Thanks very much.
     
  9. GearsAD

    GearsAD

    Joined:
    Mar 29, 2015
    Posts:
    1
    Great snippet - thanks!
     
  10. benfattino

    benfattino

    Joined:
    Nov 26, 2010
    Posts:
    43
    Amazing...
     
  11. DonLoquacious

    DonLoquacious

    Joined:
    Feb 24, 2013
    Posts:
    1,667
    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.
     
  12. potatosquadgames

    potatosquadgames

    Joined:
    Apr 16, 2017
    Posts:
    2
  13. choobyman

    choobyman

    Joined:
    Nov 2, 2016
    Posts:
    1
    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;
    }
     
  14. WF_Bart

    WF_Bart

    Joined:
    Apr 16, 2014
    Posts:
    29
    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).

    Code (CSharp):
    1.        
    2. static Bounds GetLocalBoundsForObject(GameObject go)
    3.         {
    4.             var referenceTransform = go.transform;
    5.             var b = new Bounds(Vector3.zero, Vector3.zero);
    6.             RecurseEncapsulate(referenceTransform, ref b);
    7.             return b;
    8.                        
    9.             void RecurseEncapsulate(Transform child, ref Bounds bounds)
    10.             {
    11.                 var mesh = child.GetComponent<MeshFilter>();
    12.                 if (mesh)
    13.                 {
    14.                     var lsBounds = mesh.sharedMesh.bounds;
    15.                     var wsMin = child.TransformPoint(lsBounds.center - lsBounds.extents);
    16.                     var wsMax = child.TransformPoint(lsBounds.center + lsBounds.extents);
    17.                     bounds.Encapsulate(referenceTransform.InverseTransformPoint(wsMin));
    18.                     bounds.Encapsulate(referenceTransform.InverseTransformPoint(wsMax));
    19.                 }
    20.                 foreach (Transform grandChild in child.transform)
    21.                 {
    22.                     RecurseEncapsulate(grandChild, ref bounds);
    23.                 }
    24.             }
    25.         }
    26.  
     
  15. Creiz

    Creiz

    Joined:
    Jun 6, 2017
    Posts:
    130
    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?
     
  16. Matt-Face

    Matt-Face

    Joined:
    Mar 24, 2013
    Posts:
    22
    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.
     
  17. jcl64

    jcl64

    Joined:
    Nov 20, 2021
    Posts:
    3
    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).
     
Thread Status:
Not open for further replies.