Unity + SteamVR SDKチュートリアル Part5

今回からテレポーテーションの作成に入っていきますが、まずは事前準備を進めます。
以下のチュートリアルの「Making A Laser Pointer」のパートになります
https://www.raywenderlich.com/9189-htc-vive-tutorial-for-unity

レーザーポインタの作成

テレポート先を指し示すためのレーザーポインタを作成します。仕組み的には超細長いBOXオブジェクトを作成し、レーザーポインタとして利用します。設定内容は以下の通り。

Position X:0 Y:5 Z:0
Scale X:0.005 Y:0.005 Z:1
Box Colliderコンポーネントを削除

ここまでの操作で、以下のようになっているはずです

作成したLaserオブジェクトにマテリアルを割り当てます。マテリアルは以下の手順で作成します。

RW > Materialフォルダ配下に「Laser」の名称でマテリアルを新規作成
マテリアルのShaderを「Unit/Color」に変更
プロパティのMain Colorを赤(R:255, G:0, B:0)に変更
作成したマテリアルを、先ほど作成したLaserオブジェクトに適用

ここまでの操作で、以下のような画面になります

最後に作成したLaserオブジェクトを「RW > Prefab」配下にプレハブ登録し、ヒエラルキービューからオブジェクトを削除しておきましょう。ここまでの操作で、以下のような画面になっているはずです

レーザーポインタ表示用スクリプトの作成

テレポートボタンが押されたときに、レーザーポイントが表示されるようにスクリプトを作成します。
スクリプト名は「LaserPointer」とし、「RW > Scripts」配下に作成します。
今回も、作成したスクリプトの全体像を掲載します。

using UnityEngine;
using Valve.VR;

public class LaserPointer : MonoBehaviour
{
    public SteamVR_Input_Sources handType;
    public SteamVR_Behaviour_Pose controllerPose;
    public SteamVR_Action_Boolean teleportAction;

    public GameObject laserPrefab;      // レーザーオブジェクトのプレハブを保存

    private GameObject laser;           // 作成したレーザーインスタンスの保存
    private Transform laserTransform;   // 
    private Vector3 hitPoint;           // レーザーがヒットしたポジションを保存

    // Start is called before the first frame update
    void Start()
    {
        // プレハブからレーザーインスタンスを新規作成
        laser = Instantiate(laserPrefab);
        // トランスフォーム情報を保存
        laserTransform = laser.transform;
    }

    // Update is called once per frame
    void Update()
    {
        // テレポートアクションが行われた場合
        // (動き的にはテレポートボタンが押されている場合)
        if (teleportAction.GetState(handType))
        {
            RaycastHit hit;

            // コントローラから例を飛ばし、ヒットした場合はhitに内容を保存する
            if (Physics.Raycast(controllerPose.transform.position, transform.forward, out hit, 100))
            {
                hitPoint = hit.point;
                ShowLaser(hit);
            }
        }
        else // レイがヒットしていない場合、レーザーオブジェクトの表示を消す
        {
            laser.SetActive(false);
        }
    }

    private void ShowLaser(RaycastHit hit)
    {
        // レーザーを表示
        laser.SetActive(true);
        // コントローラとレイがヒットしたポイントの間にレーザーオブジェクトを配置
        // Leapを利用する理由は、0.5を指定することで、2点間の中間にオブジェクトを配置することができるから
        laserTransform.position = Vector3.Lerp(controllerPose.transform.position, hitPoint, 0.5f);
        // レイがヒットした方向にレーザーオブジェクトを向ける
        laserTransform.LookAt(hitPoint);
        // レイがヒットした位置に合わせて、レーザーオブジェクトの大きさを変える
        laserTransform.localScale = new Vector3(laserTransform.localScale.x,
                                                laserTransform.localScale.y,
                                                hit.distance);
    }
}

作成したスクリプトをコントローラにアタッチし、各種項目を埋めていきます。
具体的な手順は以下の動画でご確認ください

動作確認

以上の設定でコントローラのテレポートボタンを押せば、レーザーが表示されるという動作が作成できているはずです。

以上

今回はここまでとなります。テレポートを実現するうえで、もう少し下準備が必要なため、次回は準備の続きを行いたいと思います。