将UI RectTransform移动到世界位置

时间:2017-07-12 00:01:21

标签: c# unity3d canvas

我有一个名为 Player 的GameObject和一个Canvas。 HealthBar GameObject是Canvas (Canvas> HealthBar)的子项。我有一个HP栏跟随玩家的脚本。它应该跟随玩家在其上方的固定位置,因此它位于精灵的顶部附近。 这是'关注' HP Follow Script的一部分。

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

问题在于HP栏随着角色一起移动,但只是玩家移动速度的一小部分。例如,如果玩家移动一个单位,则该栏移动0.1个单位。

错误视频:https://streamable.com/vaz7h

3 个答案:

答案 0 :(得分:5)

你想让一个UI对象(Image)跟随一个GameObject是SpriteRenderer或MeshRenderer。

另一方面,这可以描述为将世界点转换为UI点。

下面这个简单的函数将世界位置转换为UI空间。它需要将Canvas UI作为参数,然后将您要转换为UI位置的位置(在您的情况下为Player.transform.position变量。

移动UI对象的关键是RectTransformUtility.ScreenPointToLocalPointInRectangle函数,它将屏幕点转换为ui矩形本地点。

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);
}

<强>用法

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);
}

现在,让我们说你已经将UI定位在它应该的位置,你现在希望它跟随另一个Object(Player),你需要用上面的代码实现一个简单的偏移。这真的很容易。以下是它应该是什么样子:

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);
}

答案 1 :(得分:1)

如果画布是ScreenSpace,您可以使用:

healthbarTransform.position = camera.WorldToScreenPoint(playerTransform.position);

(如果是屏幕空间,只要你每帧设置位置,它可以是玩家的孩子或其他什么)

....关于您的问题,有一些因素可以解决问题: 您正在更新功能中设置健康栏位置,让玩家知道在玩家移动之后执行此代码,您需要在脚本执行顺序中将HPFollow脚本添加到默认时间以下(如果您要使用更新)。 或者您可以使用lateUpdate来设置ui位置。我强烈推荐。

如果你的问题只是闪烁ui,它应该是关于ui rect转换量表......

答案 2 :(得分:0)

以下是解决方案:

void Start () {
    Canvas.willRenderCanvases += canvasUpdate;
}

void canvasUpdate () {
    var screenPoint = RectTransformUtility.WorldToScreenPoint( canvas.worldCamera, worldPoint );
    Vector2 localPoint;
    RectTransformUtility.ScreenPointToLocalPointInRectangle( canvas.GetComponent<RectTransform>(), screenPoint, canvas.worldCamera, out localPoint );
    transform.localPosition = localPoint;
}