当前位置:   article > 正文

Unity 世界坐标、屏幕坐标、UGUI 坐标 相互转换_unity ugui转换世界坐标

unity ugui转换世界坐标

Unity 世界坐标、屏幕坐标、UGUI 坐标 相互转换
坐标转换是游戏开发过程中必不可少的环节
看下图 世界坐标、屏幕坐标、UI 坐标 三种坐标系的转换过程,此文章中的 UI 坐标特指 UGUI 坐标

从上图可以看到,世界坐标 和 UI 坐标 需要通过 屏幕坐标作为中间转换媒介
世界坐标 -> 屏幕坐标 -> UI 坐标
UI 坐标 -> 屏幕坐标 -> 世界坐标

屏幕坐标为 从屏幕左下角开始 坐标为 Vector2 (0, 0),
右上角结束坐标为 Vector2(Screen.width, Screen.height)

关于屏幕的坐标还有一个视口坐标 (Viewport)
视口坐标为 从屏幕左下角开始 坐标为 Vector2 (0, 0),
右上角结束坐标为 Vector2(1, 1)
本篇省略 视口坐标的转换

代码如下

首先提供一个获取 UI 摄像机的方法
UGUI 中 Canvas 的 renderMode 分为
RenderMode.ScreenSpaceOverlay、
RenderMode.ScreenSpaceCamera、
RenderMode.WorldSpace

其中 RenderMode.ScreenSpaceOverlay 不需要摄像机,其他两种需要摄像机,所以 UIManager 类需要根据 renderMode 类型处理 UICamera 的获取

  1. public class UIManager : MonoBehaviour
  2. {
  3. public static UIManager Instance;
  4. public Camera UICamera;
  5. // Start is called before the first frame update
  6. void Start()
  7. {
  8. Instance = this;
  9. Canvas canvas = GameObject.Find("Canvas").GetComponent<Canvas>();
  10. if ( canvas.renderMode == RenderMode.ScreenSpaceCamera
  11. || canvas.renderMode == RenderMode.WorldSpace)
  12. {
  13. UICamera = canvas.worldCamera;
  14. }
  15. else if (canvas.renderMode == RenderMode.ScreenSpaceOverlay)
  16. {
  17. UICamera = null;
  18. }
  19. }
  20. public static UIManager GetInstance()
  21. {
  22. return Instance;
  23. }
  24. }
  1. using UnityEngine;
  2. public class PositionConvert
  3. {
  4. /// <summary>
  5. /// 世界坐标转换为屏幕坐标
  6. /// </summary>
  7. /// <param name="worldPoint">屏幕坐标</param>
  8. /// <returns></returns>
  9. public static Vector2 WorldPointToScreenPoint(Vector3 worldPoint)
  10. {
  11. // Camera.main 世界摄像机
  12. Vector2 screenPoint = Camera.main.WorldToScreenPoint(worldPoint);
  13. return screenPoint;
  14. }
  15. /// <summary>
  16. /// 屏幕坐标转换为世界坐标
  17. /// </summary>
  18. /// <param name="screenPoint">屏幕坐标</param>
  19. /// <param name="planeZ">距离摄像机 Z 平面的距离</param>
  20. /// <returns></returns>
  21. public static Vector3 ScreenPointToWorldPoint(Vector2 screenPoint, float planeZ)
  22. {
  23. // Camera.main 世界摄像机
  24. Vector3 position = new Vector3(screenPoint.x, screenPoint.y, planeZ);
  25. Vector3 worldPoint = Camera.main.ScreenToWorldPoint(position);
  26. return worldPoint;
  27. }
  28. /
  29. // RectTransformUtility.WorldToScreenPoint
  30. // RectTransformUtility.ScreenPointToWorldPointInRectangle
  31. // RectTransformUtility.ScreenPointToLocalPointInRectangle
  32. // 上面三个坐标转换的方法使用 Camera 的地方
  33. // 当 Canvas renderMode 为 RenderMode.ScreenSpaceCamera、RenderMode.WorldSpace 时 传递参数 canvas.worldCamera
  34. // 当 Canvas renderMode 为 RenderMode.ScreenSpaceOverlay 时 传递参数 null
  35. // UI 坐标转换为屏幕坐标
  36. public static Vector2 UIPointToScreenPoint(Vector3 worldPoint)
  37. {
  38. // RectTransform:target
  39. // worldPoint = target.position;
  40. Camera uiCamera = UIManager.GetInstance().UICamera;
  41. Vector2 screenPoint = RectTransformUtility.WorldToScreenPoint(uiCamera, worldPoint);
  42. return screenPoint;
  43. }
  44. // 屏幕坐标转换为 UGUI 坐标
  45. public static Vector3 ScreenPointToUIPoint(RectTransform rt, Vector2 screenPoint)
  46. {
  47. Vector3 globalMousePos;
  48. //UI屏幕坐标转换为世界坐标
  49. Camera uiCamera = UIManager.GetInstance().UICamera;
  50. // 当 Canvas renderMode 为 RenderMode.ScreenSpaceCamera、RenderMode.WorldSpace 时 uiCamera 不能为空
  51. // 当 Canvas renderMode 为 RenderMode.ScreenSpaceOverlay 时 uiCamera 可以为空
  52. RectTransformUtility.ScreenPointToWorldPointInRectangle(rt, screenPoint, uiCamera, out globalMousePos);
  53. // 转换后的 globalMousePos 使用下面方法赋值
  54. // target 为需要使用的 UI RectTransform
  55. // rt 可以是 target.GetComponent<RectTransform>(), 也可以是 target.parent.GetComponent<RectTransform>()
  56. // target.transform.position = globalMousePos;
  57. return globalMousePos;
  58. }
  59. // 屏幕坐标转换为 UGUI RectTransform 的 anchoredPosition
  60. public static Vector2 ScreenPointToUILocalPoint(RectTransform parentRT, Vector2 screenPoint)
  61. {
  62. Vector2 localPos;
  63. Camera uiCamera = UIManager.GetInstance().UICamera;
  64. RectTransformUtility.ScreenPointToLocalPointInRectangle(parentRT, screenPoint, uiCamera, out localPos);
  65. // 转换后的 localPos 使用下面方法赋值
  66. // target 为需要使用的 UI RectTransform
  67. // parentRT 是 target.parent.GetComponent<RectTransform>()
  68. // 最后赋值 target.anchoredPosition = localPos;
  69. return localPos;
  70. }
  71. }

使用方法如下

世界坐标 -> 屏幕坐标

  1. GameObject go = GameObject.Find("GO");
  2. Vector2 screenPoint = PositionConvert.WorldPointToScreenPoint(go.transform.position);

屏幕坐标-> 世界坐标

  1. Vector2 screenPoint = new Vector2(100, 100);
  2. // 距离摄像机 Z 轴方向距离为 10
  3. float planeZ = 10;
  4. Vector3 worldPoint = PositionConvert.ScreenPointToWorldPoint(screenPoint, planeZ);

UI 坐标 -> 屏幕坐标

  1. // 获取 UGUI 组件 transform
  2. Transform dst = GameObject.Find("Canvas/Panel/Image").transform;
  3. // 将 UI transform.position 坐标转换为屏幕坐标
  4. Vector2 screenPoint = PositionConvert.UIPointToScreenPoint(dst.position);

屏幕坐标 -> UI 坐标 方法一

  1. GameObject target = GameObject.Find("Canvas/Panel1/target");
  2. RectTransform rt = target.GetComponent<RectTransform>();
  3. // 将屏幕坐标转换为 UI transform.position
  4. Vector3 uiPoint = PositionConvert.ScreenPointToUIPoint(rt, screenPoint);
  5. target.transform.position = uiPoint;

屏幕坐标 -> UI 坐标 方法二

  1. GameObject target = GameObject.Find("Canvas/Panel1/target");
  2. RectTransform targetRt = target.GetComponent<RectTransform>();
  3. // target Parent
  4. Transform parent = target.transform.parent;
  5. RectTransform parentRt = parent.GetComponent<RectTransform>();
  6. // 将屏幕坐标转换为 UI transform.position
  7. Vector3 uiPoint = PositionConvert.ScreenPointToUILocalPoint(parentRt, screenPoint);
  8. targetRt.anchoredPosition = uiPoint;

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/知新_RL/article/detail/633240
推荐阅读
相关标签
  

闽ICP备14008679号