【Unity】画面サイズと異なる大きさの RenderTexture でクリック位置の WorldPoint が取りたい話
はじめに
Unity では基本的に、 uGUI などの GUI はカメラを使って表示する 3D より手前に表示されます。
ただ、例えばポップアップウインドウのような表示がしたいなど、 GUI より手前に 3D を表示したい場合もあります。
それを解決する方法として RenderTexture を使う方法があります(正しい方法かどうかは不明)。
が、それを使って表示した内容に対してクリックし、その位置を 3D(WorldPoint) に変換しようとしたらうまくいかなかったのでメモです。
準備
- 画面サイズは 1920 * 1200 とします。
- RenderTexture のサイズは 1100 * 600 とします。
- Canvas を下記の内容で準備します。
- Canvas Scaler の UI Scale Mode を Scale with Screen Size にし、Reference Resolution を 1920 * 1200 とします。
- Raw Image を追加し、サイズを 1100 * 600 に設定します。
- 2.の Anchors を X = 0, Y = 1 に設定します。
- RenderTexture のサイズを 1100 * 600 で作成し、2.の Texture にアタッチします。
- 今回は特定の位置に置いた Plane 上のクリック位置を取ります。
- カメラの正面に Plane を適当なサイズに置きます(カメラから Z 方向に 10 離す)。
- クリック位置が分かりやすいように、適当なサイズの Cube を置きます。
(初期位置はどこでも良いです)
クリック位置を取ってみる
using System.Collections; using System.Collections.Generic; using UnityEngine; public class MainController : MonoBehaviour { public Camera MainCamera; // RenderTexture public RectTransform TextureTransform; // クリック位置上に置く Cube. public Transform ClickTransform; // Plane public Transform PlaneTransform; private Vector2 texturePosition; private Vector2 screenScale; private Vector3 screenInputPosition = Vector3.zero; private void Start () { // 実行中の画面サイズを 1920 * 1200 にスケーリング. screenScale = new Vector2( Screen.width / 1920f, Screen.height / 1200f); // 今回は RenderTexture の位置が動的に変わらないものとする. texturePosition = TextureTransform.position; } private void Update () { if(Input.GetMouseButtonUp(0)) { // クリック位置が RenderTexture でのどの位置にあるかを算出. // 座標値は画面サイズ 1920 * 1200 での値を使う必要がある. screenInputPosition.x = (Input.mousePosition.x - texturePosition.x) / screenScale.x; screenInputPosition.y = ((Input.mousePosition.y - texturePosition.y) / screenScale.y) + TextureTransform.sizeDelta.y; // クリック位置を取りたい Plane と カメラの Z 軸の差分を入れることで、 Plane 上の座標値に変換できる. screenInputPosition.z = PlaneTransform.localPosition.z - MainCamera.transform.localPosition.z; ClickTransform.position = MainCamera.ScreenToWorldPoint(screenInputPosition); } } }
注意点としては、 2D の Y 座標は画面上部が 0 、3D は下が 0 になる、というところと、 ScreenToWorldPoint に渡す座標は画面サイズが 1920 * 1200 であったときのものに合わせる必要がある、ということです。