Finding the bounds of a grouped model

I am importing a 3d model which consists of many smaller sub-parts; I would like to have a script to fire whenever the user clicks on any of the sub-part of the model. I could take a a cube gameobject and enclose it and disable the rendering, but I will have to manually size the cube.

Is there anyway to calculate the bounding area of such a grouped model? And how could I scale the cube to match that bounding area?

You can iterate through the objects and use Encapsulate to add to the total bounds from the renderers:

var combinedBounds = renderer.bounds;
var renderers = GetComponentsInChildren(Renderer);
for (var render : Renderer in renderers) {
    if (render != renderer) combinedBounds.Encapsulate(render.bounds);
}

That returns the bounds in world space; you can use mesh.bounds to get bounds in local space.

Here a snippet to get the local bounds which works for any model, no matter it is rotated or not:

void CalculateLocalBounds()
{
    Quaternion currentRotation = this.transform.rotation;
    this.transform.rotation = Quaternion.Euler(0f,0f,0f);
      
    Bounds bounds = new Bounds(this.transform.position, Vector3.zero);
      
    foreach(Renderer renderer in GetComponentsInChildren<Renderer>())
    {
        bounds.Encapsulate(renderer.bounds);
    }
      
    Vector3 localCenter = bounds.center - this.transform.position;
    bounds.center = localCenter;
    Debug.Log("The local bounds of this model is " + bounds);
      
    this.transform.rotation = currentRotation;
}

I had to resolve a similar problem recently and I came up with a solution similar to one posted by tgouala-wellfiredLtd but without having to actually rotate the parent :slight_smile:
(here I just spawn a cube to also visually show them in the correct spot)

public void TestBounds()
{
    var bounds = new Bounds(Vector3.zero, Vector3.one);
    var filters = GetComponentsInChildren<MeshFilter>();
    foreach (var meshFilter in filters)
    {
        var matrix = transform.localToWorldMatrix.inverse * meshFilter.transform.localToWorldMatrix;
        var axisAlignedBounds = GeometryUtility.CalculateBounds(meshFilter.sharedMesh.vertices, matrix);
        bounds.Encapsulate(axisAlignedBounds);
    }
    
    var boundsShower = GameObject.CreatePrimitive(PrimitiveType.Cube);
    boundsShower.name = "BOUNDS";
    boundsShower.transform.position = (transform.rotation * bounds.center) + transform.position;
    boundsShower.transform.localScale = bounds.size;
    boundsShower.transform.rotation = transform.rotation;
}