Ok, this had me stumped for a bit. It seemed as it the bounds were somehow wrong, but the code seemed to be right. However, using 3D bounds to get the onscreen bounds is where things go wrong. I used OnGUI() to draw a box around the calculated bounds, which seemed very off. But then I added a 3D bounds cube using OnDrawGizmos(). A picture says a thousand words, so here we go:
To be honest I’m not quite sure how to best proceed. Raycasting is way too expensive for something like this, so that’s out of the question.
And you can’t just convert (center + height) to screen-space either, because the center-top part of the capsule isn’t nescesarily the “highest” point in the screen-view.
I wonder if there is some shader hack you could use (i.e.: by setting and subsequently reading a Material property), but that seems very hacky and potentially costly, though I’m not too sure on the latter.
If you only have a couple of vertices you might get away with just min-maxing for all of those, instead of just the bounding box’s inside CustomGetScreenRect() (which was only an illustrative name btw; something like just GetScreenRect() is probably better. ;)). You could then maybe even optimize by doing something like “only min-max the top 9 vertices (index #0-8)”. Of course this doesn’t work for more complex shapes and can quickly get out of hand.
I may give this another look later, but for now I’m pretty much out of ideas.
Tl;dr: I have no idea! Perhaps there’s some secret GetLastFillRect() method I’ve missed, but I’m sure it can be done. The question is just… how?
EDIT: Here’s the newly added debug code I used:
void OnDrawGizmos()
{
Gizmos.color = new Color(1f, 0f, 0f, 0.4f);
Gizmos.DrawCube(enemyToFollow.transform.position + enemyToFollow.center, enemyToFollow.bounds.size);
}
void OnGUI()
{
//OnGUI() uses inverted y-axis; invert rect before drawing
Rect r = CustomGetScreenRect();
r.y = Camera.main.pixelHeight - r.y;
r.height = -r.height;
GUI.Box(r, "");
}
EDIT 2: Forgot to elaborate on why using 3D bounds is failing. While we get a close approximation, the bounding cube still suffers from perspective distortion, so the scrolling effect is just shifted to that upper “quad” (plane/ ceiling) in this case. The reason min-maxing vertices directly should work (forgot to test this, sorry!) is because you’re directly sampling the relevant points. Sorry for my in-hindsight-terrible idea of using bounding boxes!
EDIT 3: Using only the vertices indeed works, though the HP bar still shifts. The GUI.Box draws correctly though, so I’m guessing this is just an anchoredPosition quirk. I’ve never moved UI elements this way, so I’ll just leave it there for now. 