おつかれさまです。皆さまVRゲーム楽しんでらっしゃいますでしょうか?
OculusQuest2が発売されて以降、VRゲームが世の中に急速に普及している印象です。
筆者も例に漏れず、「Half-Life:Alyx」「Population One」「ALTDEUS: Beyond Chronos」とVRゲーム三昧の生活を過ごさせていただいております。
前置きが長くなりましたが、今回はOculusQuestでVRゲームを作るという記事になります。
※ OculusQuest開発の解説記事は過去にも上がっているのでぜひご覧ください。
最近のOculus Quest開発環境について
https://gaprot.jp/2020/11/12/oculus-quest-develop/
サンプルゲーム
今回はサンプルとして、以下のような雪合戦をテーマにしたゲームを用意しました。
「地面に降り積もった雪を掬って的に投げ当てる」というシンプルな内容となっています。
- Unity 2019.4.18f1
- UniversalRP 7.5.3
- Oculus Integration 25.0
今回はこのサンプルを通して、Questアプリの制作をご紹介できればと思います。
XR Plug-in Management
UnityでQuest開発を行う際には ProjectSettingsでXR Plug-in Managementを開き、AndroidのOculusプラグインを有効にする必要があります。

XR Plug-in ManagementはUnity2019.3から導入されたXRデバイスのプラグインを管理する仕組みです。
この仕組みに則ることで開発者はPackageManagerからARCoreやOculusといった必要なプラグインだけをインストールして、その後はボタン1つで入れ替えれるようになります。大変便利です。

ちなみにUnity2019.3以前はBuild-Inという形でプラグインは事前にUnityに含まれており、それを使うようになっていました。こちらの仕組みはまだ使うことができますが、既にDepracatedとなっており、Unity2020.1で廃止となっています。

Oculus Linkを利用した開発
Oculus Linkは一定品質を満たしたUSBケーブルを使ってPCとQuestを接続することで、QuestでPCVRを楽しむことができる機能です。この機能を利用して都度apkを作らずとも、Unityエディタ上でアプリの挙動を確認できます。
まずOculusをPCに繋いだ状態にして、設定画面からOculus Linkを有効にします。

次にUnityに戻り、開発環境をPCに、XR PluginをOculusに設定します。


以上で設定完了です。
エディタのプレイボタンを押すと以下のようにエディタでQuestアプリの確認ができるようになります。
UniversalRP
今回はレンダリングパイプラインに UniversalRP を選択しました。
※ UniversalRP の解説記事は過去にも上がっているのでぜひご覧ください。
UniversalRPでなんちゃってMToonシェーダーを作ってみた話
https://gaprot.jp/2020/04/14/universalrp-mtoon/
VRはレンダリング解像度が大きい上、高FPS(現状60~72fps。今後90、120fpsの解禁も)を安定して出すことが求められるため、積極的に使っていきたい機能であります。
Oculus Integration
Oculusが公式で出している専用SDKです。先ほど紹介したOculus XR Pluginをサポートするアセットになります。

カメラ設定やトラッキング、空間移動、物体へのインタラクティブ、音響とOculusのHMD用アプリを作るのに必要な実装が一通り揃っています。今回は使ってないのですが、UnityでのVRアプリの作成ツールには XR Interaction ToolKit という選択もあります。
次回は XR Interaction ToolKit の記事を載せようかと思います
VRゲーム作成について
今回はOculus Integrationを使って、VRゲームを作ってみます。
まずVRアプリを作るためには最低限以下のような挙動を用意する必要があり、ゲームはその延長線上にあるものだと思います。
- 視点
- 移動
- インタラクティブ
- UI
今回はこの挙動をどうすれば実装できるかを調べてみました。
視点
VRは基本的に一人称視点で、ユーザーが動くとキャラクターも動くというデザインが多いと思います。それを実現するためにはHMDの位置・回転を取得し、仮想空間のカメラに反映してあげる必要があります。

Oculus Integratrionには OVRPlayerController というプレハブが用意されており、これをシーンに置くだけで挙動を実現することができます。
移動
VRはさきほどの通り自分の体を動かすことでキャラクターを動かすことができます。
しかし、ゲーム内の空間が現実空間より広かったり、そもそも座って楽しみたいなどの理由でコントローラーでキャラクターの位置や向きを変えたい場合があります。
Oculus Integrationはもちろんその実装を既に備えており、Locomotionというデモシーンでその内容を確認することができます。移動はVRのキモのため、設定できる項目がとても多いです。そのため、デモシーンと合わせて以下のドキュメントを参照することをおすすめします。
ロコモーションサンプルシーン
https://developer.oculus.com/documentation/unity/unity-sf-locomotion/
今回は用意されている3種類の移動方式を試してみました。
テレポート移動
現在地から指定した目的地に対して瞬間的に移動します。

目的地を決めた次の瞬間には目的地に辿り着いており、移動中の体験が得られず味気なく感じるかもしれませんが、VRでは最も王道の移動方式でもあります。
VRをやっていて気持ち悪くなってしまったことはないでしょうか?
この体験はVR酔いと呼ばれており、VRで見ている画面とユーザーの感覚の齟齬が大きい場合に発生すると言われています。テレポート方式は移動の過程を省略して目的地に移動するので、感覚に齟齬が発生しづらく、VR酔いしづらいメリットがあります。
シフト移動
テレポートと同じく現在地から指定した目的地を設定します。その後、目的地にキャラクターが移動します。

テレポートと違い、移動中の体験を省略しませんが、VR酔いを起こしやすい側面があります。
しかし、VR酔いは先述の通り、画面と感覚の齟齬によるところが大きいです。そのため、画面の作り方によって感覚を画面に合わせやすくすることでVR酔いを抑制するアプローチもあります。
たとえば以下の方法が挙げられます。
- 進行方向に風を切るなどのエフェクトを入れて、ユーザーに移動のイメージを伝える
- 移動時にビネットを強くして、視界を狭める。
- 移動時に三人称視点に切り替える。移動完了後はまた一人称視点に戻す。
スティック移動
これまでの移動方式とは違い、目的地を設定せずにスティックを倒した方にキャラクターがシームレスに移動する方式です。

直感的で細かい位置調整が可能ですが、シフト移動と同様のデメリットがあります。
インタラクティブ
ここで言うインタラクティブとは「掴む」「投げる」といったオブジェクトへの作用を指しています。Oculus Integrationにもその実装はもちろんあり、掴む側と掴まれる側にそれぞれ専用のコンポーネントを与えることで挙動を実現できます。

今回のような手で雪玉を掴むデザインの場合、手と雪玉にそれぞれ上のようにコンポーネントを付けます。

物理挙動の制御(持ち運んでいるときは物理をOFF、手から離れた瞬間に物理をON)や、物を投げたときの初期加速度の算出など面倒なことをすべて行ってくれるのでとても便利です。
UI
最後にUIについて記載します。
UIはuGUIをVRアプリに対応させるための仕組みがあるので、それを利用するのがおすすめです。UIHelpers というプレハブが用意されており、それをシーンに配置することでOVRInputModuleというVRでUIを操作するためのモジュールを動かすことができます。

このようにVR空間に置いたキャンバスであってもレイの当たり判定があり、コントローラー操作を受け取ってボタンのイベントが発火されるようになっています。
まとめ
以上のようにUnityでVRアプリを作るためのサポートは手厚く、開発者がコンテンツの内容に注力できる環境が整っています。興味があればぜひ挑戦してみてください。