VR開発でよく使う(であろう)照準の実装とRayについて

  • 6
    いいね
  • 0
    コメント

スクリーンショット 2016-12-04 23.29.06.png

上の画像のような照準(reticle)を実装する方法です。
コントローラーが使えないスマホ用VRアプリ開発などでよく使われるかと思います。

銃の位置は適宜合わせてください。

前提

  • 照準の画像がある(なくても良いがその場合は適宜やってください)
  • カメラがある

実装

HierarchyビューでEmpty Objectを作り、それにScript(ここではRayScript)をアタッチする。

RayScript.cs
void Update () {
    Ray ray = new Ray (camera.transform.position, camera.transform.forward);
    RaycastHit hit;

    if (Physics.Raycast (ray, out hit)) {
        reticle.transform.position = hit.point;
    }
}

Rayを使ってカメラの位置から前に向かって見えない光線のようなものを飛ばしています。
Rayが当たったオブジェクトの情報をRayCastHit型の変数で受け取っていて、hit.pointで衝突したオブジェクトの位置が取れます。
それを、reticle(照準)の位置に更新しているわけです。

Rayについて

上述した通り、ある位置からある位置へ見えない光線のようなものを飛ばし、光線が衝突したオブジェクトの情報を取得できます。
今回はカメラの向いている方向にRayを飛ばしましたが、他にもたくさん便利な使い方があって、
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
のようにすると、クリックした座標に向けて、カメラからRayを飛ばすことができます。

Rayを使って敵を倒す

Rayを使えば光線の当たったオブジェクトの情報を取得できると上述しましたが、それを使っていろんな事ができます。
以前作ったアプリで敵を倒すのに使った方法の一つを紹介します。

RayScript.cs
void Update () {
    Ray ray = new Ray (diveCamera.transform.position, diveCamera.transform.forward);
    RaycastHit hit;

    if (Physics.Raycast (ray, out hit)) {
            reticle.transform.position = hit.point;

        //もしRayが衝突したオブジェクトのタグが"Monsterだったら"
        if (hit.collider.tag == "Monster") {

            //Rayが当たっている時間をincrease
            gazedTime += Time.deltaTime;

            // 発射してリセット
            if (gazedTime >= 1.4f) {
                Destroy(hit.collider.gameObject);
                gazedTime = 0;
            }
        }
    }
}

hitをRaycastHit型だとしたときに

  • hit.collider.gameobjectでRayの衝突したゲームオブジェクトが、
  • hit.collider.tagでそのゲームオブジェクトのタグが

取得できます。
照準が当たった瞬間に敵が破壊されてはつまらないので、ここではgazedTimeを定義し、1.4秒間当て続けないといけないようにしました。

おまけ

単にDestroyするだけだとつまらないので、その下でparticleなどを使って演出すると良いかもしれません。
僕はこんな感じでやってます。

Instantiate (explosion, monster.transform.position, Quaternion.identity);

explosionには、爆発っぽいparticleをアタッチしておいてます。