I know the rough size of an object can be calculated from the collider.bounds, but I want to know if there is a way to get the correct width/bounds of an object, for a sphere collider that would be the radius, for a box, it would be the extent (or the bounds if possible). The reason I want this is because I'm building an RTS game which need to show the life of each object, currently I'm using collider.bounds, but it doesn't work so well because the width changes every time I rotate the object.
I can probably just do a lookup on what collider and it is and go from there, but that would require some Collider as BoxCollider stuff, which isn't go so easy on the CPU if you got a lot of units.
Does anyone know how to do this?
asked Nov 18, 2009 at 07:25 PM
I'm not sure what you meant by "show the life of each object" - do you mean the hit points of the object are calculated from the size? If you clarify this maybe we can suggest an alternative approach.
As to your original question: if the dimensions of the object don't change then it doesn't really matter how expensive the operation to calculate the area is, because you'd only have to do it once. You might even do it in the editor (with an editor script or by hand) for that matter and store it on the prefab. But if that's too fancy, you could calculate it when the object is first created at runtime and store it on an instance variable.
Even if you need to RE-calculate the area for some reason, again you can store it on the gameObject and only recalculate it when strictly needed. At that point the expense is going to be so small that I wouldn't worry about the additional cost of figuring out which type of collider you have. I'd only worry about it if you needed to calculate it multiple times per second.
As you seem to have realized, the dimensions of the collider should not change as the object is rotated, as long as you use the parameters for that type of collider. For example, BoxCollider.size is expressed in the object's local coordinates. Contrast this with Collider.bounds, which is the bounding box in world space. As you found, it is not a good way to calculate the area unless your object is axis-aligned.
Addendum: In the comments you indicated that you aren't computing a numeric area per se, you are trying to display an overlay bar of the correct width. I'll suggest two ways to do this.
Now we just need to scale the health bar using the distance from the camera. Have a look at Camera.WorldToScreenPoint, which tells you where on the screen a point in the world would be drawn. You can use this to see where to draw the bar, and you would need to scale the width of the bar depending on how far away it is from the camera.
I hope this gives you some ideas... You could also try searching the Unity discussion forums for "health bar" to see what other people have come up with, or what problems they ran into.
Is there some reason mesh.bounds won't work for you?
answered Nov 18, 2009 at 11:37 PM
The reason the bounds size changes when you rotate the object is that the bounds represents an Axis-Aligned Bounding Box (also known as an "AABB").
If you want to get a bounding sphere, you could scan through all the object's mesh vertices to find an average vertex position (the sphere centre) and the vertex which is furthest away from the average, (which gives you the sphere's radius).
See the Mesh Documentation for an example of how to quickly loop through every vertex in your mesh.
There's a chance that your average vertex position may not be at your object's local (0,0,0) position, so you'll need to use Transform.TransformPoint() to convert it to world-space to find your real boundingsphere centre point for the gameObject.
You then have the object's bounding sphere centre position and radius!
answered Nov 18, 2009 at 08:52 PM