Hey all,
I’m just playing around with a few things at the moment for the sake of learning, and I’m struggling to find a good solution for finding the 2D position / bounds of a 3D object. Lets say for example I am making an RTS and want to show selected troops by drawing a bounding box around them I’d need to know the 2D position on the screen and then the width and height on the screen to draw the box around it. Or another example might be I am doing a hack and slash game and want to have a health bar directly above all of the ememy’s heads. Another example might be I want to put a chat bubble directly above their head in an RPG, or maybe something like damage text showing above peoples heads each time they get hit… I’m sure you get what I mean by now though.
Now I understand you can use WorldToScreen point to find the screen, and you can then use the bounds to get the width of the objects and then work out from the center there to find each of 8 bounding points and use min and max and then find what in theory would be the bounding box, but the issue I get with this is when I start rotating the object it starts to skew the size of the bounding box. You can see what I mean in this image.

The code I’m using for that is based on an example I found, which you can see here
Bounds b = renderer.bounds;
Camera cam = Camera.main;
Vector3[] pts = new Vector3[8];
float margin = 0f;
//The object is behind us
if (cam.WorldToScreenPoint (b.center).z < 0) return;
//All 8 vertices of the bounds
pts[0] = cam.WorldToScreenPoint (new Vector3 (b.center.x + b.extents.x, b.center.y + b.extents.y, b.center.z + b.extents.z));
pts[1] = cam.WorldToScreenPoint (new Vector3 (b.center.x + b.extents.x, b.center.y + b.extents.y, b.center.z - b.extents.z));
pts[2] = cam.WorldToScreenPoint (new Vector3 (b.center.x + b.extents.x, b.center.y - b.extents.y, b.center.z + b.extents.z));
pts[3] = cam.WorldToScreenPoint (new Vector3 (b.center.x + b.extents.x, b.center.y - b.extents.y, b.center.z - b.extents.z));
pts[4] = cam.WorldToScreenPoint (new Vector3 (b.center.x - b.extents.x, b.center.y + b.extents.y, b.center.z + b.extents.z));
pts[5] = cam.WorldToScreenPoint (new Vector3 (b.center.x - b.extents.x, b.center.y + b.extents.y, b.center.z - b.extents.z));
pts[6] = cam.WorldToScreenPoint (new Vector3 (b.center.x - b.extents.x, b.center.y - b.extents.y, b.center.z + b.extents.z));
pts[7] = cam.WorldToScreenPoint (new Vector3 (b.center.x - b.extents.x, b.center.y - b.extents.y, b.center.z - b.extents.z));
//Get them in GUI space
for (int i=0;i<pts.Length;i++) pts[i].y = Screen.height-pts[i].y;
//Calculate the min and max positions
Vector3 min = pts[0];
Vector3 max = pts[0];
for (int i=1;i<pts.Length;i++) {
min = Vector3.Min (min, pts[i]);
max = Vector3.Max (max, pts[i]);
}
//Construct a rect of the min and max positions and apply some margin
Rect r = Rect.MinMaxRect (min.x,min.y,max.x,max.y);
r.xMin -= margin;
r.xMax += margin;
r.yMin -= margin;
r.yMax += margin;
//Render the box
GUI.Box (r,"");
While this works, it doesn’t seem to be very accurate and if I wanted to use it I could see a few situations where being this out could definitely cause issues or just wouldn’t be ideal. Now I’m not sure if I’m doing something wrong in my code or if this is just how it works, or if there is a better way to attempt this?
I know in theory I could probably achieve all the examples I mentioned previously doing things in 3D space and just rotating them to face the camera constantly, but I’d much rather find out if there is a better more accurate way to achieve this. All my google / forum searching has given me similar to what I posted above, but I’m sure there would have to be a better way to do it.
Thanks in advance!

