Search Unity

Question WorldToScreenPoint with perspective camera returns unexpected results close to edges of the screen

Discussion in 'General Graphics' started by ankurs3thi, Apr 18, 2021.

  1. ankurs3thi

    ankurs3thi

    Joined:
    Feb 13, 2021
    Posts:
    4
    I’m building a 3D tactics game similar to Fire Emblem: Three Houses. My game has a perspective camera floating above my maps that looks down at them from an angle. The rotation of the camera in the Unity editor is (60, 60, 0).

    The camera is currently fixed, but it will eventually be able to pan, zoom, and rotate based on player input.

    I want to display health bars floating on top of of all the units on my map, similar to how other tactics/strategy games display HP (here is an example of what I mean from Dota 2). I’m able to get this sort of UI to work, but only when my units are close to the center of the screen. As they move towards the extremities, the health bars sort of drift away from where I want them to be.

    As the units move away from the camera, the bars drift upwards until they are quite a bit above my units’ heads. As the units move close to the camera, the bars drift downwards until they cover my units’ faces or upper torsos.

    This is how I’m currently creating my health bar UI:
    1. I create a screen-space Canvas in my scene. This acts as a container for all the health bars.
    2. I create a prefab for my health bars with an attached script that handles drawing the health percentage. Each health bar is itself a tiny Canvas containing some images.
    3. For each unit in the scene, I instantiate a new health bar and parent it to my screen-space Canvas. At this point, the health bars are visible and displaying each unit's health. However, they're not positioned correctly in screen-space.
    4. To position a health bar correctly, I call Camera.main.WorldToScreenPoint inside that health bar’s LateUpdate method and pass it the position of the unit the health bar is attached to. I then set the health bar’s position to the screen-space location that this method returns.

    This implementation is the same as what's demonstrated in this video. However, this example doesn't use a top-down view. I'm not sure whether the implementation simply doesn't work for a top-down game or whether I'm using it wrong.

    I have a feeling I’m making a mistake when I call WorldToScreenPoint. Do I have to add some sort of an offset to the value it returns based on my unit’s distance from the camera? Or could something be wrong with my camera settings? Or maybe I’m setting up my screen space Canvas incorrectly?

    I would really appreciate some pointers. Thanks!