transform.position = Camera.main.WorldToScreenPoint( new Vector3( origin.position.x, origin.position.y, origin.position.z ) );

I have this code on a Unity 4.6 UI object. The origin is some transform I want the UI element to stay above( like a floating health bar ).

The camera is top-down, but angled slightly on the x-axis. When the camera is moved, the UI element moves away from the origin slightly as if the camera was orthographic.

How would I go about compensating for the perspective? Is there another method I should be using to convert from world space to canvas space?

EDIT: Pictures added. Note that the transform is at the center of the model, not the base. enter image description here

  • 1
    \$\begingroup\$ Please cleatify what you want to do. \$\endgroup\$ Commented Feb 11, 2015 at 19:01
  • \$\begingroup\$ You have to just subtract y coordinate from Screen.height please check my answer below \$\endgroup\$ Commented May 19, 2016 at 7:00

3 Answers 3


You want to move 2d UI (Label) with respect to your game object. WorldToScreenPoint transform the position from world space into screen space.

Here you are on right track, what you are missing is that

screenPosition = Camera.main.WorldToScreenPoint(transform.position);
screenPosition.y = Screen.height - screenPosition.y;

So, according to me your script like this:

var screenPosition :  Vector3;

function Update (){
    screenPosition = Camera.main.WorldToScreenPoint(transform.position);
    screenPosition.y = Screen.height - screenPosition.y;

function OnGUI (){ 
    GUI.Label(Rect(screenPosition.x, screenPosition.y, 50, 20),"Health...");   


Or you can use this script: Ready to use Script (Tested & works )

using UnityEngine;
using System.Collections;
using System;

public class SingleLbl : MonoBehaviour {

    private bool mShowGUIButton = false;
    public GameObject targetObject;
    public float btnWidth = 400f;
    public float btnHeight = 180f;

    void Start () {


    void OnGUI ()
        // Find the 2D position of the object using the main camera
        Vector3 boxPosition = Camera.main.WorldToScreenPoint(targetObject.transform.position);

        // "Flip" it into screen coordinates
        boxPosition.y = Screen.height - boxPosition.y;

        // Center the label over the coordinates
        //boxPosition.x -= boxW * 0.5f;
        //boxPosition.y -= boxH * 0.5f;

        GUI.Button(new Rect(boxPosition.x, boxPosition.y, btnWidth , btnHeight), targetObject.name);
        Debug.Log (boxPosition.z + "--x--" + boxPosition.x + "----y--" + boxPosition.y);


  • \$\begingroup\$ Thanks for the answer, man. Also thanks for reminding me about this question. However, I made a stupid mistake and didn't realise the transform origin is actually at his feet, meaning it's working perfectly. I'll delete this question soon. \$\endgroup\$
    – Ben
    Commented May 19, 2016 at 7:06
  • \$\begingroup\$ :) at first me too do the same..never mind.. .but other ll learn from it \$\endgroup\$ Commented May 19, 2016 at 7:43

would it be better for you to add a object you can reference as a child of the game object. It could be damage1 or something and then on a trigger you could

Instantiate(damage1, transform.position, transform.rotation);

you could then set that to a animation effect like moving up and fading out or whatever effect you like.

  • \$\begingroup\$ I don't think you understand the problem. The GUI isn't in world space. Setting the position isn't the problem, the conversion from world space to screen space is. \$\endgroup\$
    – Ben
    Commented Feb 11, 2015 at 16:14
  • \$\begingroup\$ Are you just trying to add a damage effect? like he gets hit and it show -1 damage text. I was suggesting another way to implement without all the worldspace to screenspace calculations. \$\endgroup\$ Commented Feb 11, 2015 at 16:24
  • \$\begingroup\$ Yeah. I don't understand how this would solve the problem, though. We want the text to be on the a child of the canvas, not a world space object. \$\endgroup\$
    – Ben
    Commented Feb 11, 2015 at 16:25
  • \$\begingroup\$ damage1 would be gameobject with a TextMesh and animation on it in the example I showed. you would get your desired effect. but if you must have it a child of the canvas then sorry for suggesting a method that doesn't fit your needs. \$\endgroup\$ Commented Feb 11, 2015 at 16:35
  • \$\begingroup\$ Yeah, I should have clarified, I'd much prefer to use the new Unity UI stuff. A TextMesh seems a bit unnecessary here. \$\endgroup\$
    – Ben
    Commented Feb 11, 2015 at 18:20

you can add this to the update function of your UI object:

transform.forward = -Camera.main.gameObject.transform.forward;
  • \$\begingroup\$ This just seems to mess up the GUI element. \$\endgroup\$
    – Ben
    Commented Feb 11, 2015 at 16:15

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .