最近在做新手引导,涉及到UI中查找子对象,并需要将子对象的坐标转换到最外层Canvas中的坐标,看了很多人的帖子,其中雨松的帖子提供了一个转换方式,但是并不能解决由于对子对象锚点,注册点的自定义而造成的位置偏差。
通过研究发现,注册点、锚点是ugui为了做自适应方案提供的,但在世界坐标系中,是没有这些区分的,那么要解决上述ugui中子对象由于注册点、锚点的不一致而造成的偏差,我们可以做如下转换:
1 首先将子对象的世界坐标位置转换成屏幕坐标位置
2 再将转换后的屏幕坐标转换到Canvas区域中的局部坐标
3 进行注册点偏移矫正
/// <summary> /// 子对象坐标转换到Canvas的局部坐标 /// </summary> /// <param name="current"></param> /// <param name="canvas"></param> /// <returns></returns> public static Vector2 TransformToCanvasLocalPosition(this Transform current, Canvas canvas) { var screenPos = canvas.worldCamera.WorldToScreenPoint(current.transform.position); Vector2 localPos; RectTransformUtility.ScreenPointToLocalPointInRectangle(canvas.GetComponent<RectTransform>(), screenPos, canvas.worldCamera, out localPos); return localPos; }
这是对Transform的一种扩展写法
具体使用如下,target是你要参考坐标转换的目标对象
var pos = target.transform.TransformToCanvasLocalPosition(MainUiCanvas); var rtr = target.GetComponent<RectTransform>();
//注册点偏移矫正 pos.x = pos.x + (float)(rtr.rect.width * (rectTransform.pivot.x - rtr.pivot.x)); pos.y = pos.y + (float)(rtr.rect.height * (rectTransform.pivot.y - rtr.pivot.y));
rectTransform.anchoredPosition = pos;
至此 ,输出的局部坐标位置,就是这个子对象在Canvas中的位置(锚点居中,注册点居中)。这样,你就可以轻松的创建一个新手引导的提示对象,放置于该局部坐标位置。