Bounds Finding Box

I am trying to get the bounds of a weirdly shaped thing with crazy meshness. I get it that it is not as easy as gameObject.bounds. I figured the easiest way (based on the inconclusive results in my research) is to put a box such as a collider or cube around each gameObject, and just grab the bounds of that. My question is, what object should I use? Is there an object out there that is already intended for this? Or do I need to make a cube and make it translucent and such?

Final Question:

What do I wrap around a GameObject in order to get the bounds of that GameObject via the wrapper?

I’m assuming you want an AABB (Axis Aligned Bounting Box) around all of the objects. If you need the best possible bounds:

  • Take the mesh.bounds from each object.
  • Calculate the eight corners
  • For each corner, convert it from local to world space using Transform.TransformPoint().
  • Find the minimum and maximum x,y, and z. Coordinate.
  • Repeat with each game object using the same x, y, and z minimums and maximums.

At the end you will have the minimum and maximum values of a box around all of your objects. If you need it, it would be easy to construct a bounds from that data.

Here are two functions. GetBounds() creates an axes aligned bounding box around an array of game objects. GetBoundsPointsNoAlloc() takes a game object and a Vector3[8], and fill the array with the mesh bounding box in world space. These points are not axes aligned. They are both static functions, so if you have a Utility class where you keep static functions, you can toss them in there:

using UnityEngine;
using System.Collections;

public static class Utils {

// Gets an axis aligned bound box around an array of game objects
	public static Bounds GetBounds(GameObject[] objs) {
		if (objs == null || objs.Length == 0) {
			return new Bounds(Vector3.zero, Vector3.zero);
		}

		float minX =  Mathf.Infinity;
		float maxX = -Mathf.Infinity;
		float minY =  Mathf.Infinity;
		float maxY = -Mathf.Infinity;
		float minZ =  Mathf.Infinity;
		float maxZ = -Mathf.Infinity;

		Vector3[] points = new Vector3[8];

		foreach (GameObject go in objs) {
			GetBoundsPointsNoAlloc(go, points);
			foreach (Vector3 v in points) {
				if (v.x < minX) minX = v.x;
				if (v.x > maxX) maxX = v.x;
				if (v.y < minY) minY = v.y;
				if (v.y > maxY) maxY = v.y;
				if (v.z < minZ) minZ = v.z;
				if (v.z > maxZ) maxZ = v.z;
			}
		}
	
		float sizeX = maxX - minX;
		float sizeY = maxY - minY;
		float sizeZ = maxZ - minZ;

		Vector3 center = new Vector3(minX + sizeX / 2.0f, minY + sizeY / 2.0f, minZ + sizeZ / 2.0f);

		return new Bounds(center, new Vector3(sizeX, sizeY, sizeZ));
	}

// Pass in a game object and a Vector3[8], and the corners of the mesh.bounds in 
//   in world space are returned in the passed array;
	public static void GetBoundsPointsNoAlloc(GameObject go, Vector3[] points) {
		if (points == null || points.Length < 8) {
			Debug.Log ("Bad Array");
            return;
		}
		MeshFilter mf = go.GetComponent<MeshFilter>();
		if (mf == null) {
			Debug.Log ("No MeshFilter on object");
			for (int i = 0; i < points.Length; i++)
				points *= go.transform.position;*
  •  	return;*
    
  •  }*
    
  •  Transform tr = go.transform;*
    
  •  Vector3 v3Center  = mf.mesh.bounds.center;*
    
  •  Vector3 v3ext = mf.mesh.bounds.extents;*
    
  •  points[0]  = tr.TransformPoint(new Vector3(v3Center.x - v3ext.x, v3Center.y + v3ext.y, v3Center.z - v3ext.z));  // Front top left corner*
    
  •  points[1]  = tr.TransformPoint(new Vector3(v3Center.x + v3ext.x, v3Center.y + v3ext.y, v3Center.z - v3ext.z));  // Front top right corner*
    
  •  points[2]  = tr.TransformPoint(new Vector3(v3Center.x - v3ext.x, v3Center.y - v3ext.y, v3Center.z - v3ext.z));  // Front bottom left corner*
    
  •  points[3]  = tr.TransformPoint(new Vector3(v3Center.x + v3ext.x, v3Center.y - v3ext.y, v3Center.z - v3ext.z));  // Front bottom right corner*
    
  •  points[4]  = tr.TransformPoint(new Vector3(v3Center.x - v3ext.x, v3Center.y + v3ext.y, v3Center.z + v3ext.z));  // Back top left corner*
    
  •  points[5]  = tr.TransformPoint(new Vector3(v3Center.x + v3ext.x, v3Center.y + v3ext.y, v3Center.z + v3ext.z));  // Back top right corner*
    
  •  points[6]  = tr.TransformPoint(new Vector3(v3Center.x - v3ext.x, v3Center.y - v3ext.y, v3Center.z + v3ext.z));  // Back bottom left corner*
    
  •  points[7]  = tr.TransformPoint(new Vector3(v3Center.x + v3ext.x, v3Center.y - v3ext.y, v3Center.z + v3ext.z));  // Back bottom right corner*
    
  • }*
    }

    And here is a class that I used to test the code. If you want to see the bounding box in Game view, you will need Gizmos turned on in the upper right corner of the Game window:
    using UnityEngine;
    using System.Collections;

public class Testing : MonoBehaviour {

Bounds bounds;

void Update() {
bounds = Utils.GetBounds (GameObject.FindGameObjectsWithTag(“Enemy”));
}

void OnDrawGizmos() {
Gizmos.DrawWireCube (bounds.center, bounds.size);
}
}