RectTransformUtilityを使ってスクリーン座標をRectTransform上ののローカル座標やワールド座標に変換する方法です。
Unity2018.3.1
スクリーン座標をRectTransform上のUIのローカル座標に変換する
スクリーン座標をUIのローカル座標に変換するにはRectTransformUtility.ScreenPointToLocalPointInRectangle
を使います。
これは、スクリーン座標を引数に与えたRectTransform平面上の点に変換します。
using UnityEngine; using UnityEngine.UI; [RequireComponent(typeof(Graphic))] public class Example : MonoBehaviour { [SerializeField] private GameObject _obj; void Update() { if (Input.GetMouseButtonDown(0)) { // クリックしたスクリーン座標 var screenPoint = Input.mousePosition; // Canvasにセットされているカメラを取得 var graphic = GetComponent<Graphic>(); var camera = graphic.canvas.worldCamera; // Overlayの場合はScreenPointToLocalPointInRectangleにnullを渡さないといけないので書き換える if (graphic.canvas.renderMode == RenderMode.ScreenSpaceOverlay) { camera = null; } // クリック位置に対応するRectTransformのlocalPositionを計算する var localPoint = Vector2.zero; RectTransformUtility.ScreenPointToLocalPointInRectangle(graphic.rectTransform, screenPoint, camera, out localPoint); // ローカル座標にインスタンス生成 var instance = Instantiate(_obj, transform); instance.GetComponent<RectTransform>().localPosition = localPoint; instance.SetActive(true); } } }
引数にCameraがありますが、Render ModeがオーバーレイのときにはCameraをnullにしないといけないので注意が必要です。
結果はこんな感じになります。
Render ModeをWorldにしてPerspectiveなCameraを使えばこんなことも。
スクリーン座標をRectTransform平面上のワールド座標に変換する
スクリーン座標をワールド座標に変換するにはScreenPointToWorldPointInRectangleを使います。
using UnityEngine; using UnityEngine.UI; [RequireComponent(typeof(Graphic))] public class Example : MonoBehaviour { [SerializeField] private GameObject _obj; void Update() { if (Input.GetMouseButtonDown(0)) { // クリックしたスクリーン座標 var screenPoint = Input.mousePosition; // Canvasにセットされているカメラを取得 var graphic = GetComponent<Graphic>(); var camera = graphic.canvas.worldCamera; // Overlayの場合はScreenPointToWorldPointInRectangleにnullを渡さないといけないので書き換える if (graphic.canvas.renderMode == RenderMode.ScreenSpaceOverlay) { camera = null; } // クリック位置に対応するRectTransform上のワールド座標を計算する var worldPoint = Vector3.zero; RectTransformUtility.ScreenPointToWorldPointInRectangle(graphic.rectTransform, screenPoint, camera, out worldPoint); // ワールド座標にインスタンス生成 var instance = Instantiate(_obj); instance.transform.position = worldPoint; instance.SetActive(true); } } }
こちらもRender ModeがオーバーレイのときにはCameraをnullにしないといけないので注意が必要です。
結果はこのようになります。
ワールド座標をスクリーン座標に変換
ワールド座標をスクリーン座標に変換するにはRectTransformUtility.WorldToScreenPoint
を使います。
using UnityEngine; using UnityEngine.UI; [RequireComponent(typeof(Graphic))] public class Example : MonoBehaviour { [SerializeField] private Transform _transform; [SerializeField] private Camera _camera; void Update() { var camera = _camera; // Cameraにnullを入れるとOverlay用のCameraのスクリーン座標が得られる var screenPos = RectTransformUtility.WorldToScreenPoint(camera, _transform.position); Debug.Log(screenPos); } }
どのカメラにとってのスクリーン座標に変換するのかを定義しなければならないのでCameraを渡すわけですが、
Overlay用のCameraにおけるスクリーン座標に変換したい場合にはCameraにnullを渡します。