1.世界坐标转屏幕坐标,再转换UI坐标
RectTransformUtility.ScreenPointToWorldPointInRectangle将一个屏幕空间点转换为 RectTransform 的本地空间中位于其矩形平面上的一个位置。
ScreenPointToWorldPointInRectangle的RectTransform参数,最好使用此UI的Canvas。这样计算的ui坐标z轴比较稳定。
cam 参数应为与此屏幕点关联的摄像机。对于设置为 Screen Space - Overlay 模式的 Canvas 中的 RectTransform,cam 参数应为 null。
//此方法的摄像机用可以看到物体的摄像机。
Vector2 screenPos = Camera.main.WorldToScreenPoint(targetObj.transform.position);
//此方法的摄像机用UI摄像机,。
RectTransformUtility.ScreenPointToWorldPointInRectangle(rt, screenPos, Camera.main,out Vector3 outPos);
rt.position = outPos;
注意:由于基于摄像机进行了两次运算,此方法计算的结果,由于精度问题,会有一点偏差,导致ui抖动。
如写在Update或LateUpdate中,可能会随Camera移动,产生大幅抖动。卸载FixedUpdate会抖动小一些。因此我是用了第二种方法。
2.世界坐标转屏幕坐标,将屏幕坐标计算为UI的localPosition
首先还是世界坐标转换为屏幕坐标
//此方法的摄像机用可以看到物体的摄像机。
Vector2 screenPos = Camera.main.WorldToScreenPoint(targetObj.transform.position);
屏幕坐标的原点(0,0)在左下角,右上角为(Screen.width,Screen.heigth)
UI坐标的原点(0,0)在正中心,所以我们要减去偏移量(Screen.width / 2, Screen.heigth / 2)。
考虑到UI的层级关系,需减去父物体的localPosition。
screenPos.x -= Screen.width / 2;
screenPos.y -= Screen.height / 2;
while (rt.parent != null && rt.parent.GetComponent<Canvas>() == null)
{
screenPos -= rt.parent.localPosition;
rt = rt.parent;
}
再将最后得到的坐标赋值给ui。
完整代码
//此方法的摄像机用可以看到物体的摄像机。
Vector2 screenPos = Camera.main.WorldToScreenPoint(targetObj.transform.position);
screenPos.x -= Screen.width / 2;
screenPos.y -= Screen.height / 2;
while (rt.parent != null && rt.parent.GetComponent<Canvas>() == null)
{
screenPos -= rt.parent.localPosition;
rt = rt.parent;
}
rt.position = outPos;
此方式不会造成UI抖动。