0
\$\begingroup\$

Here is what I want to achieve, health bars that stay perfectly above the units, regardless of where the unit moves or where the camera is: https://www.youtube.com/live/fZSaPDz-GJc?si=B868wwF5KAPCuEtw&t=3305

I've tried all sort of things, both having my canvas in world-space and screen-space.

In world-space I cannot get my canvas to properly stay in position above the unit, while always facing the camera.

transform.rotation = Quaternion.LookRotation(transform.position - Camera.main.transform.position); 

I also tried without - Camera.main.transform.position and also with + instead, nothing has the desired result and I can't quite wrap my brain around how all of this works. Another thing I tried is this, both with and without the y freeze.

Vector3 forward = _cam.transform.forward; forward.y = 0; forward.Normalize(); healthbarCanvas.transform.forward = forward; 

This makes the edges of my health bar go up/down as the camera moves, it doesn't stay horizontal like it should.

In screen space I got pretty close, but it's still moving a bit when I'm moving my camera and the health bar also gets bigger/smaller as I zoom in/out.

public override void OnLateUpdateView() { Vector3 offset = new Vector3(0, 3.5f, 0); Vector3 worldPos = transform.position + offset; Vector3 screenPos = _cam.WorldToScreenPoint(worldPos); healthbar.transform.position = screenPos; } 

I've tried several variations, like freezing the y rotation, freezing the z rotation, but nothing works exactly as I need it to work.

I want health bars that stay exactly above my unit as it moves around in 3D space, regardless of camera position, angle or zoom. Exactly like the health bars in League of Legends above the champions and minions work.

As suggested I tried:

transform.rotation = Quaternion.LookRotation(camera.forward, camera.up); 

Which results in this: From far:
from far

From nearby:
from naerby


Someone in the Unity Discord suggested using an Ortographic camera instead, which does solve this issue perfectly. Is it possible with a Perspective camera?

\$\endgroup\$
2
  • \$\begingroup\$ Can you define "stay perfectly above" this could be: #1 project the characters position into screen space and then move up by 15 pixels, #2 Choose a point 1 meter above the characters head in world space then project that point into screen space, #3 Something else. Without a precise definition of what you are trying to achieve this question is not answerable. \$\endgroup\$ Commented Jun 17 at 10:17
  • \$\begingroup\$ Is it possible that your world-space canvas is a lot larger than the stuff visible on it? So it doesn't rotate around the point you think it should be rotating around? \$\endgroup\$ Commented Jun 17 at 11:34

1 Answer 1

1
\$\begingroup\$

Try:

// Cache this if you can, to avoid searching for it multiple times each frame. var camera = Camera.main.transform; transform.rotation = Quaternion.LookRotation(camera.forward, camera.up); 
\$\endgroup\$
6
  • \$\begingroup\$ I've tried this as well (with and without camera.up) and it both results in the health bar just staying in a static location, seemingly unattached to the unit. So when the camera is far, it will look like it's above the unit, but the closer you move the camera to the unit, the bigger the space between the unit & health bar becomes. \$\endgroup\$ Commented Jun 15 at 17:22
  • \$\begingroup\$ Changing the rotation won't change the position. If you're finding the position tracking is not to your liking (not mentioned in your comments on your world-space attempts), then it could be that the pivot of your health bar is in the wrong place relative to the visible graphic, or you've chosen the wrong offset from the unit position. It could also be an illusion, where the spacing is constant in world space, leading to a larger/smaller pixel offset as you zoom, or constant in screen space, making it appear to change relative to the unit's world-space size. \$\endgroup\$ Commented Jun 15 at 17:23
  • \$\begingroup\$ Try editing your question to show images/video illustrating the specific mismatch with one specific set of code. \$\endgroup\$ Commented Jun 15 at 17:24
  • \$\begingroup\$ Can I add videos here? \$\endgroup\$ Commented Jun 15 at 17:29
  • 1
    \$\begingroup\$ You probably just need to scale the distance from the unit to the healthbar according to the distance from the unit to the camera. 1. Get the distance to the camera, e.g. with float distanceToCamera = Vector3.Distance(Camera.main.transform.position, unit.transform.position); 2. Apply some formula (you'll have to experiment) to convert this to healthbar distance, e.g. float healthBarDistance = Mathf.Clamp(Mathf.Sqrt(distanceToCamera), 0.2f, 2f); 3. Position the healthbar (e.g. healthBar.transform.position = unit.transform.position + Vector3.up * healthBarDistance; \$\endgroup\$ Commented Jun 17 at 17:56

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.