今回はUnityのワールドポイントとビューポートポイントとスクリーンポイントについて見ていきたいと思います。
流れとしてはワールドポイントとビューポートポイントとスクリーンポイントが何なのか?を見ていった後で、3Dゲームオブジェクトの位置をそれぞれに変換するサンプルを作成して理解を深めます。
ワールドポイント
ワールドポイントは3D空間上の位置を表します。
なので左右のX座標、上下のY座標、手前と奥のZ座標を使って表します。
スクリプトではVector3を使って
1 2 3 | new Vector3(10f, 20f, 5f); |
等のように使っています。
ビューポートポイント
ビューポートはカメラで表示している領域の事で、ビューポートポイントは上下左右を0~1の間で正規化した座標で表します。
カメラの描画範囲の左下の座標はXが0でYが0、右下はXが1でYが0、左上はXが0でYが1、右上はXが1でYが1となります。
0~1の範囲を超えた場合はその点が描画範囲から外れたことを意味します。
スクリーンポイント
スクリーンポイントはカメラで表示している領域をピクセルで表した位置です。
例えばUnityメニューのEdit→Project Settings→PlayerのResolution and PresentationのFullscreen ModeをWindowedにしてDefault Screen Widthを1024、Default Screen Heightを768とした場合は左下の座標はXが0、Yが0、右下はXが1023、Yが0、左上はXが0、Yが1023、右上はXが1023、Yが767となります。
ゲーム画面のサイズが変わるとスクリーンポイントも変わってきます。
ワールド空間、ビューポート空間、スクリーン空間の位置を変換してみる
ワールド空間、ビューポート空間、スクリーン空間の位置の変換をするメソッドが用意されているので、それらを使って位置の変換をしてみましょう。
わかりやすくする為にMain CameraゲームオブジェクトのTransformを以下のようにします。
ヒエラルキーで右クリックから3D Object→Sphereを選択し、Transformを以下のようにします。
新しくConversationTestというスクリプトを作成し、Sphereに取り付けます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | using System.Collections; using System.Collections.Generic; using UnityEngine; public class ConversionTest : MonoBehaviour { // Update is called once per frame void Update() { // ゲームオブジェクトのワールドポイント Debug.Log("ワールド空間の位置: " + transform.position); // このスクリプトを設定したゲームオブジェクトの位置をビューポートポイントに変換し、コンソールに表示する Debug.Log("ビューポートポイント " + Camera.main.WorldToViewportPoint(transform.position)); // このスクリプトが取り付けられたゲームオブジェクトの位置をスクリーンポイントに変換して表示する Debug.Log("スクリーンポイント: " + Camera.main.WorldToScreenPoint(transform.position)); } } |
Camera.mainでMainCameraタグが取り付けられたカメラを取得出来、そのカメラからWorldToViewportPointメソッドを使って、このスクリプトが取り付けられたSphereの位置をビューポートポイントに変換し、それをコンソールに出力しています。
Camera.main.WorldToScreenPointメソッドではスクリーンポイントに変換しています。
シーンビューでSphereを移動させるとコンソールにワールドポイント、ビューポートポイントとスクリーンポイントが表示されます。
初期の状態だと以下のような感じで表示されます。
シーンビューでSphereをカメラの描画範囲の右上の方に移動させると以下のように表示されます。
あくまで点なのでUnityのプリミティブな図形であるCubeやSphereの一部がカメラ内に映っていても、基点となる位置は図形の中心に設定されているので、図形の一部がカメラに描画されていても基点がカメラ外にあれば、ビューポートの0~1の範囲外、スクリーンポイントの範囲外の値が表示されます。
今回使用したメソッドの他にも
ScreenToViewportPoint スクリーンポイントからビューポイント
ScreenToWorldPoint スクリーンポイントからワールドポイント
ViewportToScreenPoint ビューポートポイントからスクリーンポイント
ViewportToWorldPoint ビューポートポイントからワールドポイント
等があります。
その他
ViewportPointToRay ビューポートポイントからレイを飛ばす
ScreenPointToRay スクリーンポイントからレイを飛ばす
といったメソッドもあるのでUnityスクリプトリファレンスのCameraを見てください。
終わりに
ワールド空間からビューポート空間やスクリーン空間の位置がわかると3D上のゲームオブジェクトの動きに合わせて2D上のUIの位置を変更するといった機能を作ることが出来ますね。
それを実際に使ったのが
FPSゲーム等でカメラの中心から弾を発射したい時はViewportPointToRayメソッドを使えばビューポートポイントの中心座標であるnew Vector3(0.5f, 0.5f, 0f)からレイを飛ばしてその情報から敵に当たったかどうかといった情報を得る事が出来ます。