i-school - VRアクションゲーム UIのボタンをポインターでクリックする

設計


 Oculus Integration アセットの機能を利用して、VR 空間にボタンを設置し、
コントローラーの先端から Ray を発射して、Ray が当たった位置にあるボタンを押せるようにする機能を実装します。

 通常のゲームと異なり、VR 空間では UI 関連を空間内に表示させた方がゲームの臨場感・VR の特別感が出ます。

 今回はその先駆けとして、VR 空間に UI のボタンを表示させて、そのボタンを空間内で押す機能を設計します。
多くの機能は Oculus Integration アセットによって補うことができますので、足りない部分を補填して完成させます。

 段階的に実装を行っていく必要がありますので、設計手順をまとめておきます。


 ・プレイヤーの機能
    => Oculus Integration アセットに含まれている OVRPlayerController(OVRCameraRig) プレファブを利用する
      VR 空間用のカメラ機能も含まれる
 
 ・Ray を発射する機能
    => Oculus Integration アセットに含まれている UIHelper プレファブと、その中にあるコンポーネントを利用する
      OVRPlayerController(OVRCameraRig) の機能も利用して、VR 用のコントローラーから Ray を発射する

 ・Ray を認識する機能
    => Canvas 内のボタンを Ray が認識できるように、Oculus Integration アセットに含まれている OVR Raycaster コンポーネントを利用する

 この他に、ボタンにアタッチするスクリプトと、Canvas の表示制御を行うスクリプトを自作します。

 順番に実装をしていきますので、全体の流れをイメージしながら制作を行っていきましょう。



ゲームの舞台を準備する


 プレイヤーなどを設置するための地面用のゲームオブジェクトを作成します。

 ヒエラルキーの空いている場所で右クリックをしてメニューを開き、3D > Plane を選択します。

 サンプルとして作成するので、とくにサイズなども調整せずとも問題ありません。


OVRPlayerController ゲームオブジェクトを配置し、設定を行う


 Oculus Integration アセットに含まれているプレファブを活用します。
下記のフォルダにある OVRPlayerController プレファブをヒエラルキーにドラッグアンドドロップして設置します。

Assets/Oculus/VR/Prefabs/OVRPlayerController.prefab


 このゲームオブジェクトには OVRCameraRig というカメラのゲームオブジェクトもふくまれているため、
Main Camera ゲームオブジェクトは削除するか、非アクティブの状態にしておきます。

 OVRPlayerController ゲームオブジェクトに Rigidbody コンポーネントと CapsuleCollider コンポーネントを追加します。
Rigidbody は Constraints の設定の Rotation の部分にすべてチェックを入れておきます。
コライダーのサイズは適宜調整してください。

OVRPlayerController ゲームオブジェクトのインスペクター画像例



 なお、自作の PlayerController の場合も作り方は同じです。


自作の OVRPlayerController ゲームオブジェクトのインスペクター画像例





 つづいて、設定を行います。
OVRPlayerController ゲームオブジェクトを展開して階層内を見れる状態にします。

 OVRPlayerController > OVRCameraRig > TrackingSpace > LeftHandAnchor > LeftControllerAnchor の
子オブジェクトとして、OculusTouchForQuestAndRiftS_Left モデルを追加します。

OculusTouchForQuestAndRiftS_Left モデルのパス
Assets/Oculus/VR/Meshes/OculusTouchForQuestAndRiftS/OculusTouchForQuestAndRiftS_Left.fbx



 おなじように、OVRPlayerController > OVRCameraRig > TrackingSpace > RightHandAnchor > RightControllerAnchor の子オブジェクトとして
OculusTouchForQuestAndRiftS_Right モデルを追加します。

OculusTouchForQuestAndRiftS_Right モデルのパス
Assets/Oculus/VR/Meshes/OculusTouchForQuestAndRiftS/OculusTouchForQuestAndRiftS_Right.fbx


ヒエラルキー画像



 以上で設定は完了です。


ワールド空間に Canvas を設置して設定を行う


 ヒエラルキーに Canvas を作成します。一緒に EventSystem ゲームオブジェクトが作成されますので、
EventSystem ゲームオブジェクトはヒエラルキーから削除してください。後程別のゲームオブジェクトにより代用します。

 そのままでは VR 空間に対応しないため、インスペクターの設定を行います。


 
 RenderMode を World Space に変更します。これにより、VR 空間内に Canvas が配置されるようにします。
サイズが大きくなるため、Scale を小さくして調整し、任意の位置に設置してください

 EventCamera には OVRPlayerController > OVRCameraRig > TrackingSpace > CenterEyeAnchor ゲームオブジェクトをアサインします。
CenterEyeAnchor ゲームオブジェクトには Camera コンポーネントがアタッチされていますので、それを Canvas を描画する Camera の情報として利用する設定にします。
最後に Graphic Raycaster コンポーネントを Remove するか、非アクティブの状態にし、代わりに OVR Raycaster コンポーネントをアタッチします。
このコンポーネントは Oculus Integration アセットに含まれているものです。これにより、VR 空間内での Ray を感知できるようにします。


インスペクター画像



Scene ビュー画像


 以上で設定は完了です。


Canvas 内に Button を作成し、設定を行う


 通常の UI を作成するのと同じように、Canvas の子オブジェクトとして Button ゲームオブジェクトを作成します。
この Button に Ray を発射して、Ray が当たっている場合に、Button をクリックさせて Button に登録されたイベント(メソッド)を実行します。

 また BoxCollider コンポーネントを追加して、ボタンにコライダーを設定します。
ボタンのサイズに合わせて調整して設定をおこなってください。


インスペクター画像



Scene ビュー画像


 以上で設定は完了です。


Button の制御を行うための ItemButton スクリプトを作成する


 Button に Ray が当たってボタンを押すことが出来た際に、実際に実行する処理を制御するクラスを作成します。
処理の内容はボタンにより変わるため、まずはボタンの押下処理が実行されているかを確認するためのメソッドを作り、
その中でデバッグを実行して挙動確認を行います。

 実際にメソッドが呼び出されていることが確認できたら、メソッドの内容をボタンを押した際に処理したい内容に書き替えるようにします。


ItemButton.cs


 スクリプトを作成したらセーブします。


Button に ItemButton スクリプトをアタッチする


 Button ゲームオブジェクトに ItemButton スクリプトをドラッグアンドドロップしてアタッチします。




 以上で設定は完了です。


UIHelper ゲームオブジェクトを配置する


 Oculus Integration アセットに含まれている UIHelper プレファブをヒエラルキーにドラッグアンドドロップして配置します。
このゲームオブジェクト群を利用することで、Ray を発射し、ゲーム画面内に可視化させて、ボタンを操作するようにします。

Assets/Oculus/SampleFramework/Core/DebugUI/Prefabs/UIHelpers.prefab


ヒエラルキー画像



UIHelper ゲームオブジェクトの設定を行う


 UIHepler ゲームオブジェクトには子オブジェクトが3つあります。
このうち、LaserPointer ゲームオブジェクトと EventSystem ゲームオブジェクトにアタッチされている各コンポーネントの修正を行います。



 LaserPointer ゲームオブジェクトのインスペクターより LineRenderer コンポーネントの設定を行います。
 
 なお、初期設定で LineRenderer コンポーネントが非アクティブになっているのは、VR コントローラーから特定のボタンを押したときだけ
LineRenderer がアクティブになり、その後、押していない間は再度、非アクティブにするためです。
よって、この部分はこの後に作成するスクリプトで制御を行うため、非アクティブのままで構いません


インスペクター画像



 Color の部分を設定すると、Ray を投射した際に表示されるラインの色を設定できます。
初期の色は白ですが、希望であれば、任意の色に設定してください。グラデーションも可能です。

 Materials の配列が 1 になっていますが、Element 0 には Missing となっており、マテリアルの情報がありません。
こちらも任意のマテリアルをアサインしてください。自作しても構いません。この設定を行わないと LineRenderer が描画を行わないので注意してください。
この例では、Unity に含まれている Sprites - Default マテリアルを設定しています。


 以上で、LineRenderer の設定は完了です。


インスペクター画像




 続いて EventSystem ゲームオブジェクトのインスペクターより、OVRInputModule コンポーネントの設定を行います。

 Canvas 作成時に自動的にヒエラルキーに追加された EventSystem ゲームオブジェクトを削除してもらっているのは、
このゲームオブジェクトには EventSystem コンポーネントがアタッチされているためです。

 OVRInputModule コンポーネント内の Ray Transform の部分に、Ray を発射するゲームオブジェクトをアサインします。
この例では、左のコントローラーを利用する予定であるため、OVRPlayerController ゲームオブジェクト内にある LeftHandAnchor ゲームオブジェクトをアサインしています。

 Joy Pad Click Button では、Ray を発射するボタンを設定します。このボタンを押したときだけ、Ray が発射されて、その軌道を LineRenderer が描画します。
この部分も左のコントローラーのボタンを利用するため、Primary Index Trigger (左コントローラーの人差し指トリガー)を設定しています。

 右のコントローラーから Ray を発射したい場合には、どちらの設定も右用に変更してください。

 
インスペクター画像



 以上で設定は完了です。


MenuController スクリプトを作成する


 このままでも処理は問題なく動きますが、Canvas が表示されているときだけ、LineRenderer コンポーネントが起動するように制御を行います。


MenuController.cs


 スクリプトを作成したらセーブします。


MenuController スクリプトをゲームオブジェクトにアタッチして設定を行う


 新しくゲームオブジェクトを作成するか、Canvas ゲームオブジェクトなどの既存のゲームオブジェクトに MenuController スクリプトをアタッチしてください。

 各変数に制御を行うコンポーネントをアサインして登録します。

 CanvasObj 変数には Canvas ゲームオブジェクトをドラッグアンドドロップしてアサインします。

 LineRenderer 変数には、UIHepler ゲームオブジェクトの子オブジェクトである LaserPointer ゲームオブジェクトをドラッグアンドドロップしてアサインします。
自動的に LineRenderer コンポーネントの情報が登録されます。


ヒエラルキー画像



 以上で設定は完了です。


実機にてゲームを実行して挙動を確認する


 実機用にビルドを行い、ゲームを実行してください。

 左コントローラーの X ボタンを押して、Canvas が表示/非表示されるかを、何回か切り替えて確認します。

 Canvas が表示されている際に、左コントローラーの人差し指トリガーを引いてください。
ゲーム画面内に Ray が発射されて、その軌道が見えるようになれば成功です。
その Ray をボタンの位置で投射し、ボタンが押されたことになると、ボタンのイベントに登録したメソッドが実行されて、デバッグが表示されます。



 以上で完成です。