world pos -> ui local pos
世界坐标转UI局部坐标比较常用,也比较简单。
Vector3 worldPosition = _3dTransform.position;
Vector3 screenPosition = _3dCamera.WorldToScreenPoint(worldPosition);
Vector2 localPostion;
if (RectTransformUtility.ScreenPointToLocalPointInRectangle((RectTransform)_canvas.transform, screenPosition, _canvas.worldCamera, out localPostion))
{
_2dTransform.localPosition = localPostion;
}
ui local pos -> world pos
-
如果知道UI物件,直接通过transform.position获得。
-
如果只知道UI父节点以及一个相对于父节点的局部坐标,可以通过:
worldPos = parentTransform.TransformPoint(localPos);
-
如果只知道一个UI坐标,需要先转到屏幕坐标系,再转到世界坐标系:
首先主要考虑的是UI适配,通常canvas scale会设置成Scale With Screen Size,Canvas大小就不一定是屏幕分辨率的大小。
假设原本的标准分辨率是720x1280,在ipad的分辨率1536x2048上显示时:
假如是以高度为适配,那么Canvas 实际高度为1280,宽度为1536 / 2048 * 1280 = 960,拉伸比例为2048 / 1280 = 1.6;
假如是以宽度为适配,那么Canvas实际宽度为720,高度为2048 / 1536 * 720 = 960,拉伸比例为1536 / 720 = 2.13;
那么屏幕坐标 = Canvas下的UI局部坐标 * 拉伸比例 + 屏幕宽高 / 2;
因为Canvas UI局部坐标系的原点在中间,而屏幕坐标系的原点在左下角。
接着再通过ScreenToWorldPoint(screenPos)转为世界坐标。
代码如下:
var standardSize = new Vector2(720f, 1280f);
var scale = canvasScaler.matchWidthOrHeight == 0
? Screen.width / standardSize.x
: Screen.height / standardSize.y;
var screenPos = localPos * scale + 0.5f * new Vector2(Screen.width, Screen.height);
var worldPos = new Vector3();
RectTransformUtility.ScreenPointToWorldPointInRectangle((RectTransform) canvas.transform, screenPos, uiCamera, out worldPos);
- 如果只是为了获得偏移,可以简单地通过比例来获得:
worldOffsetY / uicamera.orthographicSize * 2 = uiOffsetY / Screen.height