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 
(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;
}