マウス操作とスクリーン座標 (4/4)
作成:2014-09-15 09:56
更新:2014-09-15 09:56
更新:2014-09-15 09:56
■ゲームオブジェクトをクリックしたか調べる
ここまで来たら、「ゲームオブジェクトをクリックして操作する」というのもやってみましょう。これは、座標変換の他に「Ray(レイ、光線)」というものを使う必要があります。
ゲームオブジェクトをクリックしたか?というのは、つまり、「クリックした地点にゲームオブジェクトがあるか」を調べることです。が、クリックした地点というのはスクリーン座標の2次元上であり、3次元空間には「奥行き」もあります。クリックした地点にゲームオブジェクトがあるか?といっても、その地点からずっと離れた奥の方にゲームオブジェクトがあるかもしれません。
ワールド座標では、ゲームオブジェクトがどれだけ離れているかわからないのです。従って、調べるためには、「クリックした地点から、ず~~っと奥のほうまで何かないか調べる」という必要があります。
これを行うのが「Ray」です。これは、カメラから、指定の地点を通って3次元空間の無限の果てまで伸びる直線です。この線に何かが触れていないかを調べることで、「指定した地点の延長線上にゲームオブジェクトがあるかどうか」を知ることができます。
・指定した地点を通過するRayを作る
・Rayとオブジェクトが衝突してないか調べる
まず、ScreenPointToRayメソッドを呼び出して、引数に指定した地点を通過するRayインスタンスを作成します。そして、Physicsクラスの「Raycast」というメソッドを呼び出して、Rayと衝突しているオブジェクトがないか調べます。返値がtrueなら、何か衝突しています。
では、衝突しているオブジェクトはどうやってしるのか? それが、第2引数の「Raycast」です。この引数には「out」というのがついていますが、これは、この引数に値が設定されることを示します。つまり実行すると、この第2引数に設定していた変数に、衝突していたゲームオブジェクトに関する情報をまとめたRaycastというクラスのインスタンスが代入されるのです。このRaycastインスタンスには以下のようなプロパティが用意されています。
transform――衝突したゲームオブジェクトのtransform。これのメソッドを呼び出してゲームオブジェクトを操作できる。
position――衝突した地点を示す値。Vector3の値。
collider――衝突したゲームオブジェクトのcollider。これのgameObjectプロパティで、ゲームオブジェクト本体が得られる。
これらを利用することでクリックしたゲームオブジェクトを知ることができます。下に利用例を挙げておきます。シーンにあるCubeをクリックすると、黄色に変わります(一定時間経過すると元の色に戻ります)。クリックしたオブジェクトを得るまでの流れをまとめると以下のようになります。
1.Input.mousePositionでクリックしたスクリーン座標を得る。
2.Camera.main.ScreenPointToRayでRayインスタンスを作成する。
3.Physics.Raycastで、Rayを通過するオブジェクトがあるかチェックする。
4.オブジェクトがあったら、生成されたRaycastHitのcollider.gameObjectからクリックしたゲームオブジェクトを取り出す。
――ちょっとややこしいので、サンプルをベースにいろいろ書き換えたりしてプログラムの動きを確認してみましょう。ここまでの説明がひと通り理解できれば、マウス操作はだいたいできるようになりますよ!
ゲームオブジェクトをクリックしたか?というのは、つまり、「クリックした地点にゲームオブジェクトがあるか」を調べることです。が、クリックした地点というのはスクリーン座標の2次元上であり、3次元空間には「奥行き」もあります。クリックした地点にゲームオブジェクトがあるか?といっても、その地点からずっと離れた奥の方にゲームオブジェクトがあるかもしれません。
ワールド座標では、ゲームオブジェクトがどれだけ離れているかわからないのです。従って、調べるためには、「クリックした地点から、ず~~っと奥のほうまで何かないか調べる」という必要があります。
これを行うのが「Ray」です。これは、カメラから、指定の地点を通って3次元空間の無限の果てまで伸びる直線です。この線に何かが触れていないかを調べることで、「指定した地点の延長線上にゲームオブジェクトがあるかどうか」を知ることができます。
・指定した地点を通過するRayを作る
Ray 変数 = Camera.main.ScreenPointToRay( 《Vector3》);
・Rayとオブジェクトが衝突してないか調べる
bool 変数 = Physics.Raycast(《Ray》, out 《Raycast》, 長さ );
まず、ScreenPointToRayメソッドを呼び出して、引数に指定した地点を通過するRayインスタンスを作成します。そして、Physicsクラスの「Raycast」というメソッドを呼び出して、Rayと衝突しているオブジェクトがないか調べます。返値がtrueなら、何か衝突しています。
では、衝突しているオブジェクトはどうやってしるのか? それが、第2引数の「Raycast」です。この引数には「out」というのがついていますが、これは、この引数に値が設定されることを示します。つまり実行すると、この第2引数に設定していた変数に、衝突していたゲームオブジェクトに関する情報をまとめたRaycastというクラスのインスタンスが代入されるのです。このRaycastインスタンスには以下のようなプロパティが用意されています。
transform――衝突したゲームオブジェクトのtransform。これのメソッドを呼び出してゲームオブジェクトを操作できる。
position――衝突した地点を示す値。Vector3の値。
collider――衝突したゲームオブジェクトのcollider。これのgameObjectプロパティで、ゲームオブジェクト本体が得られる。
これらを利用することでクリックしたゲームオブジェクトを知ることができます。下に利用例を挙げておきます。シーンにあるCubeをクリックすると、黄色に変わります(一定時間経過すると元の色に戻ります)。クリックしたオブジェクトを得るまでの流れをまとめると以下のようになります。
1.Input.mousePositionでクリックしたスクリーン座標を得る。
2.Camera.main.ScreenPointToRayでRayインスタンスを作成する。
3.Physics.Raycastで、Rayを通過するオブジェクトがあるかチェックする。
4.オブジェクトがあったら、生成されたRaycastHitのcollider.gameObjectからクリックしたゲームオブジェクトを取り出す。
――ちょっとややこしいので、サンプルをベースにいろいろ書き換えたりしてプログラムの動きを確認してみましょう。ここまでの説明がひと通り理解できれば、マウス操作はだいたいできるようになりますよ!
(by. SYODA-Tuyano.)
※プログラムリストが表示されない場合
AddBlockなどの広告ブロックツールがONになっていると、プログラムリスト等が表示されない場合があります。これらのツールをOFFにしてみてください。
●プログラム・リスト●
using UnityEngine; using System.Collections; public class myscript : MonoBehaviour { GameObject obj; Color c; bool flg = false; int counter = 0; void Start () { } void Update () { transform.Rotate(1,1,1); if (Input.GetMouseButtonDown(0)){ Vector3 pos = Input.mousePosition; Ray ray = Camera.main.ScreenPointToRay(pos); RaycastHit hit; if (Physics.Raycast(ray, out hit, 100f)){ obj = hit.collider.gameObject; c = obj.renderer.material.color; obj.renderer.material.color = Color.yellow; counter = 100; flg = true; } } if (flg){ if(--counter == 0){ flg = false; obj.renderer.material.color = c; } } } }
※関連コンテンツ