目次
関連記事一覧
OculusQuest2(その1) VRで物を掴む投げる離す
OculusQuest2(その3) UI←今回の記事
はじめに
UIはゲームを作る上で、必要不可欠なものです。
通常UIのクリックイベントはUnity標準で実装されているので、それほど意識しなくても問題なく実装できると思います。
しかし、VRではUIのイベントを発生するシステムを変更しないと、UIの操作ができません。
今回はOculusVR上でどのようにUI操作を実装すれば良いのかについて書いていきます。
今回作成したサンプル
VR用にイベントシステムを変更すれば、UI側のコンポーネントの実装を変えることなくUIの操作が可能になります。
※実機ではキャンバスとの接地点に、丸いポインターが表示されますが、キャプチャ動画だと表示されていませんでした。
実装方法
プレイヤーのセットアップ
こちらに関しましては、前回の記事に書いてありますのでご参照ください。
ワールド空間にキャンバスを設置
Canvasにデフォルトでついている、GraphicRaycasterコンポーネントを削除し、
Oculus Integrationに含まれている、OVRRayCasterを追加します。
EventSystemを変更
Canvasを生成した時に、自動的に追加されるEventSystemの
StandaloneInputModuleを削除し、Oculus Integrationに含まれているOVRInputModuleを追加します。
今回は右コントローラーからレイを飛ばして操作したいので、以下の様に右手のアンカーを設定します。
JoyPadClickButtonでは、UIを操作するボタンを指定できます。
今回は右手の人差し指トリガーボタンを指定しました。
コントローラーからレイを飛ばしてUI操作
Oculus Integrationに含まれているUIサンプルでは、視点からレイを飛ばすものがありました。
しかし、ほとんどのVRゲームはコントローラーからレイを飛ばしているので、この方法が標準だと思います。
上記のEventSystemの設定をすれば、コントローラーからレイを飛ばして判定することは可能ですが、ポインターの表示ができません。
公式のサンプルを確認すると、OVRGazePointerがポインターの表示を行っています。
しかし、こちらは視線用なのでコントローラーには使用できませんでした。
OVRGazePointerはOVRCursorを継承しているので、こちらを継承したクラスを新しく作成することで対応可能です。
1 2 3 4 5 |
abstract public class OVRCursor : MonoBehaviour { public abstract void SetCursorRay(Transform ray); public abstract void SetCursorStartDest(Vector3 start, Vector3 dest, Vector3 normal); } |
SetCursorRayは今回処理を定義しませんでした。
SetCursorStartDestは、レイを飛ばし、Canvasに触れた際、
start: レイの始点
dest: レイが衝突した点
normal: 例の方向(今回は未使用)
が送られてきます。
こちらが今回作成したクラスになります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
using UnityEngine; [RequireComponent(typeof(LineRenderer))] public class MyRayPointer : OVRCursor { [SerializeField] private GameObject _pointerObj; private LineRenderer _lineRenderer; private bool _isCalledSetCursorCurrentFrame; void Start() { _lineRenderer = GetComponent<LineRenderer>(); _lineRenderer.positionCount = 2; _lineRenderer.enabled = false; _pointerObj.SetActive(false); } private void LateUpdate() { if (!_isCalledSetCursorCurrentFrame) { _lineRenderer.enabled = false; _pointerObj.SetActive(false); } _isCalledSetCursorCurrentFrame = false; } public override void SetCursorRay(Transform ray) { } public override void SetCursorStartDest(Vector3 start, Vector3 dest, Vector3 normal) { _lineRenderer.enabled = true; _isCalledSetCursorCurrentFrame = true; _pointerObj.SetActive(true); _lineRenderer.SetPosition(0, start); _lineRenderer.SetPosition(1, dest); transform.position = dest; } } |
EmptyObjectを作成し、こちらをAddComponentします。
LineRendererも自動で追加されます。こちらは適切な表示になる様に調整してください。
さらに先ほど作成したオブジェクトの子に、3DObjectのQuadを追加します。
こちらは、レイがCanvasと衝突した際に表示するポインターです。
こちらに、OVROverlayを追加し、
QuadのMaterialには、Oculus/UnlitTransparentシェーダーを使用したマテリアルを、
OVROverlayのTexturesには左右に使用するポインターの画像を設定します。
次にMyRayPointerに上記のQuadオブジェクトを設定します。
最後にEventSystemに作成したオブジェクトを追加して設定完了です。
VR用EventSystemの仕組み
今回のEventの流れを図にまとめると以下になります。
EventSystemを書き換えることで、UIのEventを自前で発生できます。
最初はBaseInputModuleを継承して自前で実装しようとしましたが、
公式が用意してくれていることを知り、 利用させていただくことにしました。
まとめ
一度VR用のModuleを作成すれば、UI側は何も変更することなく利用できます。
拡張できる様に設計されている点が素晴らしいと感じました。
普段の業務でも仕様が追加されることに対して対応ができる設計をしていきたいです。