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?
Answer by Bampf
Nov 18, 2009 at 09:10 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.
A good non-mathematical approach would be to simply add the bar as a small polygon (preusmably a quadrilateral) to the unit itself. (Either make it a child gameobject of the unit, or make it follow the unit around.) That way the bar would move around with the unit, and get smaller as it moves further away. Then you would just need to billboard the polygon so that it always faces the camera. You would get for free a cool effect where the health bar would be obscured by objects in front of it... But if you want the bar to always be visible, you could change the bar's shader to make it always draw on top, and you should in either case use a shader that is self-lit, not reflecting lights in the scene.
If you prefer to do it mathematically though, what you need is the size of the unit (which we discussed above) after it has been projected by the camera onto the screen. A quick approximation of this would be to take a number representing the size of the unit (could be computed from the collider as already discussed, or just assign a "health bar width" to each type of unit manually at design time.)
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.
Ok, I will make my question a bit more clear:
The collider.bounds returns a box containing the object which is axis aligned, I want to have a box around the object but it should be aligned to the local space.
But I guess I will have to pre compute the box for all objects at startup as you said, and then rotate it during runtime depending on the rotation of the object (the width wont need changing though).
PS: You know in all RTS games you see a thin green line over each unit showing the life, I need to calculate the width of that line for each unit, since I building will have a much longer line than a machine gun guy.
Ah, I misunderstood what you were asking. I thought you were trying to compute the area as a number. Precomputing the size will only work if the viewed size of the object doesn't vary. For example, if the game is 2D or if you are using isomorphic projection. I will add to my original answer to discuss.
Answer by duck
Nov 18, 2009 at 08:52 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!
Answer by Jessy
Nov 18, 2009 at 11:37 PM
Is there some reason mesh.bounds won't work for you?
Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.
The best place to ask and answer questions about development with Unity.
To help users navigate the site we have posted a user guide.
If you are a new user, check out our FAQ for more information.
If you are a moderator, see our Moderator Guidelines page.
We are making improvements to UA, see the list of changes.
For troubleshooting common problems with Unity 5.x Editor (including Win 10).
Answers and Comments
No one has followed this question yet.
The name 'Joystick' does not denote a valid type ('not found')
Issue using Vector3.Reflect to bounce a ball
Concave rotation Collision problem
RigidBody Script Conflict
Error on checking collision or code desync?