将UI RectTransform移动到世界位置

我有一个名为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个单位。

错误video: https : //streamable.com/vaz7h

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

换句话说,这可以被描述为将世界点转换为UI点。

下面这个简单的函数将世界位置转换为UI空间。 它将UI的Canvas作为参数,然后将您要转换为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(播放器),您需要使用上面的代码实现一个简单的偏移。 这真的很容易。 下面是它应该是什么样子:

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

如果canvas是ScreenSpace,您可以使用:

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

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

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

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

这是解决方案:

 void Start () { Canvas.willRenderCanvases += canvasUpdate; } void canvasUpdate () { var screenPoint = RectTransformUtility.WorldToScreenPoint( canvas.worldCamera, worldPoint ); Vector2 localPoint; RectTransformUtility.ScreenPointToLocalPointInRectangle( canvas.GetComponent(), screenPoint, canvas.worldCamera, out localPoint ); transform.localPosition = localPoint; }