Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Move UI RectTransform to world position

Tags:

c#

canvas

unity3d

I have a GameObject named Player, and a Canvas. The HealthBar GameObject is a child of the Canvas (Canvas>HealthBar). I have the HP bar following the player with a script. It is supposed to follow the player at a fixed position above it, so it sits near the top of the sprite. Here is the 'follow' part of the HP Follow Script.

        void Update () 
{
    Vector3 currentPos = transform.position;
    Vector3 playerPos = Camera.main.WorldToViewportPoint (Player.transform.position);
    transform.position = playerPos;

The problem is that the HP bar moves with the character, but at a very small fraction of the speed of which the player is moving. For example, if the player moves one unit, the bar moves 0.1 units.

Video of error: https://streamable.com/vaz7h

like image 687
David Rios Avatar asked Jul 12 '17 00:07

David Rios


People also ask

How do you convert from canvas space to world space?

Set the Canvas to World SpaceSelect your Canvas and change the Render Mode to World Space. Now your Canvas is already positioned in the World and can be seen by all cameras if they are pointed at it, but it is probably huge compared to other objects in your Scene.

How do I change the rect transform position in unity?

For a non-stretching Rect Transform, the position is set most easily by setting the anchoredPosition and the sizeDelta properties. The anchoredPosition specifies the position of the pivot relative to the anchors. The sizeDelta is just the same as the size when there's no stretching. Save this answer.

What is unity canvas?

The Canvas is the basic component of Unity UI. It generates meshes that represent the UI Elements placed on it, regenerates the meshes when UI Elements change, and issues draw calls to the GPU so that the UI is actually displayed.


1 Answers

You want to make a UI Object(Image) follow a GameObject is a SpriteRenderer or MeshRenderer.

In another way, this can be described as converting world point to UI point.

This simple function below converts world position to UI space. It takes a the Canvas of the UI as parameter then the position you want to convert to UI position which in your case is the Player.transform.position variable.

The key for moving a UI object is the RectTransformUtility.ScreenPointToLocalPointInRectangle function which converts the screen point to ui rectangle local point.

public Vector3 worldToUISpace(Canvas parentCanvas, Vector3 worldPos)
{
    //Convert the world for screen point so that it can be used with ScreenPointToLocalPointInRectangle function
    Vector3 screenPos = Camera.main.WorldToScreenPoint(worldPos);
    Vector2 movePos;

    //Convert the screenpoint to ui rectangle local point
    RectTransformUtility.ScreenPointToLocalPointInRectangle(parentCanvas.transform as RectTransform, screenPos, parentCanvas.worldCamera, out movePos);
    //Convert the local point to world point
    return parentCanvas.transform.TransformPoint(movePos);
}

Usage:

public GameObject Player;
public Canvas canvas;
void Update()
{
    //Convert the player's position to the UI space then apply the offset
    transform.position = worldToUISpace(canvas, Player.transform.position);
}

Now, let's say that you have already positioned the UI to be where it is supposed to be and you now want it to follow another Object(Player), you need to implement a simple offset with the code above. This is really easy. Below is what it is supposed to look like:

public GameObject Player;
public Canvas canvas;


Vector3 Offset = Vector3.zero;

void Start()
{
    Offset = transform.position - worldToUISpace(canvas, Player.transform.position);
}

void Update()
{
    //Convert the player's position to the UI space then apply the offset
    transform.position = worldToUISpace(canvas, Player.transform.position) + Offset;
}

public Vector3 worldToUISpace(Canvas parentCanvas, Vector3 worldPos)
{
    //Convert the world for screen point so that it can be used with ScreenPointToLocalPointInRectangle function
    Vector3 screenPos = Camera.main.WorldToScreenPoint(worldPos);
    Vector2 movePos;

    //Convert the screenpoint to ui rectangle local point
    RectTransformUtility.ScreenPointToLocalPointInRectangle(parentCanvas.transform as RectTransform, screenPos, parentCanvas.worldCamera, out movePos);
    //Convert the local point to world point
    return parentCanvas.transform.TransformPoint(movePos);
}
like image 175
Programmer Avatar answered Sep 21 '22 17:09

Programmer