Bounds Around Multiple Targets

Hi All,

After some searching about on this forum (and others) I still find myself perplexed. I hope this isn’t reiterating another asked question. The nearest I found was this: calculating the object bounds of the group of objects - Questions & Answers - Unity Discussions , but this doesn’t seem to quite do it.

Basically I’m attempting to find the total bounds of a number of independent game objects, so I can point my camera at them and make sure the player isn’t missing any of the action.

It’s my approach rather than the code I’m questioning, so rather than drop in a load of code, here’s what I’m attempting to do:

  • Gather all the GameObjects of interest in one list
  • Encapsulate the GameObjects within one Bounds
  • Use this Bounds to move and zoom the main camera

The two problems with this approach I’ve found:

Bounds.Encapsulate() will only work if you’ve centered the Bounds correctly first. But to do that you need to do some maths upfront. I’d be happy to strip out the X & Z positions and then work out the center, but this feels messy to me. Is there not a way to group everything and basically say: Give me the total Bounds.

Bounds only deals with a single Axis. This is not a problem right now (the game is similar to an RTS game, so ground based units), but might become one later where things high up could be missed.

Am I going about this in the right way? Is there a better technique to understand the space in which a group of objects exists within?

Thanks in advance everyone.

Do not initialize your bounds to zero - take initial bounds from first object and then expand it using other objects. This way bounds won’t include (0,0,0) point unless it has to.

I have a way that you might implement for your problem.

objectArray = GameObject.FindGameObjectsWithTag("objectTag");

Get all your objects into the array, however you will, with tags or what you are using.

		xtempmax = objectArray[0].transform.position.x;
	for (int i = 1; i < objectArray.Length; i++) {
		if (objectArray*.transform.position.x > xtempmax) {*

_ xtempmax = objectArray*.transform.position.x;_
_
}_
_
}_
_
xtempmin = objectArray[0].transform.position.x;_
_
for (int i = 1; i < objectArray.Length; i++) {_
_ if (objectArray.transform.position.x < xtempmin) {
xtempmin = objectArray.transform.position.x;
}
}
//Y AVERAGE*

* ytempmax = objectArray[0].transform.position.y;
for (int i = 1; i < objectArray.Length; i++) {
if (objectArray.transform.position.y > ytempmax) {
ytempmax = objectArray.transform.position.y;
}
}
ytempmin = objectArray[0].transform.position.y;
for (int i = 1; i < objectArray.Length; i++) {
if (objectArray.transform.position.y < ytempmin) {
ytempmin = objectArray.transform.position.y;
}
}
//Z AVERAGE*

* ztempmax = objectArray[0].transform.position.z;
for (int i = 1; i < objectArray.Length; i++) {
if (objectArray.transform.position.z > ztempmax) {
ztempmax = objectArray.transform.position.z;
}
}
ztempmin = objectArray[0].transform.position.z;
for (int i = 1; i < objectArray.Length; i++) {
if (objectArray.transform.position.z < ztempmin) {
ztempmin = objectArray.transform.position.z;
}
}
Get your max and min bounds for all your things.
Then move the camera based off of those, for example if you wish to centre the camera:
Vector3 newpos = new Vector3((xtempmax+xtempmin)/2, (ytempmax+ytempmin)/2, (ztempmax+ztempmin)/2);
You have the average of those positions stored in newpos and you can lerp the camera to that position._

__*
Although you’re doing it “the long way” sometimes it ends up being much more flexible in the end. I had trouble with getting bounds working properly with one of my games and this is what I used instead.

You could calculate the bounds center of a GameObject array with the function below:

function CalcCenter(objs: GameObject[]): Vector3 {
  var min = Vector3.one * Mathf.Infinity;
  var max = Vector3.one * Mathf.NegativeInfinity;
  for (var obj: GameObject in objs){
    var box = obj.renderer.bounds; // or use obj.collider.bounds
    min = Vector3.Min(min, box.min); // expand min to encapsulate bounds.min
    max = Vector3.Max(max, box.max); // expand max to encapsulate bounds.max
  }
  return (max+min)/2;
}

Get the objects of interest in an array, then call CalcCenter to get the center point. I suppose renderer.bounds is what you need, since this will contain all the mesh - collider.bounds may be smaller or greater than the mesh.

Thank you all.

So I realise I’d tried using the first objects bounds prior, but had stupidly forgot to reset the bounds each update, therefore making it pointless. I’ve ended up with this code, which seems tobe working…

	bool isReset = false;
	foreach (GameObject gameObject in theAction) {
		if (isReset == false) { 
			actionView = new Bounds(gameObject.transform.position, new Vector3(1,1,1));
			isReset = true;
		}
		actionView.Encapsulate(gameObject.transform.position);
	}

Where theAction is a List of Game Objects, and Action View is the bounds.

You may be able to help with a small niggle. I was trying to simply reset actionView to null, and test for actionView = null rather than a seperate bool, isReset. But due to null not being of Type Bounds I get an error. How would you reset a Bounds variable?

Thanks again