今回はVR開発ネタをやっていきます。
開発に使うのはOculusQuestですがRift Sなどにもそのまま応用できるかと思います。
VRアプリを体験されたり、遊んでいる方はこのようなUIを見たことがあるかと思います。
首を振ったり、辺りを見渡すとUIが少し遅れて追従してきますね。
(参考:Robo Recall)
Oculus Integarationに入ってそうですが見つからなかったので、今回はこれを作ってみます。
- 開発環境
- セットアップ
- 実際にCanvasを作ってみる
- 必要なコンポーネントの準備
- UIのセットアップ
- UIがオブジェクトに隠れてしまう時の対処法
- アクティブな2つ目以降のCameraが正常に動かなくなる問題の解決
- まとめ
- その他
- 余談
- 参考文献
開発環境
Unity 2019.4.0f1
Oculus Integration ver17.0
Oculus Quest
セットアップ
まだProjectを作っていない方や初めてVR開発をする方はこちらを参考にしてみてください。
すでに作成済みの方は次へ。
今回はこのようなSceneを用意しました。
何もないSceneにPlaneとOVRPlayerControllerを設置しています。(Planeは描画だけ切っています)
Cameraさえあればなんでもいいです。
実際にCanvasを作ってみる
VRでは、UIはワールド座標に配置することがほとんどで、
非VRゲームのような画面に張り付けるタイプのUIは少なめです。
UnityではCanvasのRender Modeを変えることでワールド座標に配置することができます。
ただし、Canvasを作っていきなりモードを変えると設定が少し面倒なので以下の方法がオススメです。
テラシュールブログさんのやり方でCanvasを作ってみます。
Canvasの作成
Canvas - Render ModeをScreenSpace-Cameraに変更
CanvasコンポーネントのRender ModeをScreen Space - Cameraに変更します。
Render CameraにはSceneに配置されているCameraを設定します。
設定するのはOVRCameraRig/TrackingSpace/CenterEyeAnchorです。
Plane DIstanceを調整
次にPlane Distanceを設定します。これはCameraとCanvas間の距離です。
プレイヤーに追従するUIとしてなら2~5くらいがちょうどいいかもしれません。
これにより、Cameraの前方にCanvasが移動します。大きさもいい感じです。
Canvas - Render ModeをWorld Spaceに変更
最後にCanvasのRender ModeをWorld Spaceにして完成です。
このやり方ならCanvasのWidth/HeightやScaleを自力で調整する手間がなくなります。
ImageやTextの配置
後は適当に画像や文字を配置していけばそれっぽいUIの出来上がりです。
必要なコンポーネントの準備
今回やりたいことを実現するためのScriptはこちら。コピペなどでProjectに入れてください。
FollowHUD
Targetを追跡して、位置や角度を追従するコンポーネントです。
このコンポーネントがアタッチされたオブジェクトの子にCanvasを置きます。
パラメータ
Target:
追従するターゲットのTransformです。設定されていない場合Main Cameraを自動的に取得します。
FollowMoveSpeed:
移動速度です。
FollowRotateSpeed:
回転速度です。
RotateSpeedThreshold:
UIとTargetの角度を常に計算し、一定以上離れたら回転速度を上げるようにしています。
このパラメータはそのしきい値です。
isImmediateMove:
有効にすることで位置のみ瞬時に同期するようになります。
isLock:
有効にすることで回転しないようにできます。XYZ個別に設定できます。
文章を表示するUIはZ軸をLockしておくとよさそう。
CameraEnable
UI Cameraにアタッチすることで、シーン開始時にCameraを再有効化します。
UIのセットアップ
先ほど作ったCanvasとコンポーネントを使って、視点から遅れて追従するUIを作ってみます。
HUDの作成
空のGameObjectを作り、名前を「HUD」(なんでもいい)に変えます。
作ったWorldSpaceのCanvasをHUDの子オブジェクトにします。
HUDにFollowCameraコンポーネントをアタッチします。Cameraの設定はしなくても大丈夫です。
他パラメータはお好みで。
これで完成です。
UIの細かい位置や速度などは実際に動かしながら調整するといいでしょう。
CanvasのPositionなどを調整
HUDのPositionはCameraと同じ値にしておくと調整が楽になります。
Cameraからの距離はCanvasを、細かい位置や角度はUI部品個別に調整するといいかも。
ちなみに、HUDを複数用意してSpeedを変えておくとバラバラに追従します。
UIがオブジェクトに隠れてしまう時の対処法
WorldSpaceのUIの問題点として他のオブジェクトに隠れてしまう点があります。
床や壁、多数のオブジェクトがある場合困りますね。
対処方としては、UI用のCameraを新たに作成するのが手っ取り早いです。
Cameraの作成
CenterEyeAnchorをDuplicate(オブジェクトの複製)し、名前をUI Cameraに変更します。
Audio Listenerは消しておきましょう。
UIのみ映るようにする
CameraコンポーネントのCulling MaskをUIのみに設定します。
CameraはCulling Maskに設定したレイヤーのオブジェクトのみ描画します。
Clear FlagsをDepth onlyに
Clear FlagsをDepth onlyにします。
元のCameraにUIは映らないようにする
CenterEyeAnchorのCulling MaskからUIを外しておきます。
これでUIだけ映らなくなります。
これで完成・・・ではないんです。実はもう一段落あります
アクティブな2つ目以降のCameraが正常に動かなくなる問題の解決
Scene内にアクティブなCameraが複数ある場合、1つを除いて正常に動かなくなる場合があります。
Oculus Integrationの何かがやっているとは思いますが、原因はわからず。。。
一度Cameraのenableを切り替えたり、オブジェクト自体の再アクティブ化を行えば治ります。
先ほど紹介したCameraEnableコンポーネントをそのままアタッチすれば問題ありません。
これで完成です。
地形や障害物に影響されず最前列にUIが表示されるようになりました。
まとめ
・FollowHUDコンポーネントを使うことで、視点から遅れて追従するUIを作る
・UIが他のオブジェクトに隠れてしまう場合は、UI用のCameraを作ることで最前列に表示できる
その他
この記事を書いている最中に良さそうなアセットを見つけました。
紹介記事はこちら
余談
HoloLensの話ですが、実はこのようなオブジェクトの配置方法はBody-Lockedと呼ばれているそうです。
HoloLens でのオブジェクトの配置は大きく 3 種類にわけられ、Body-Locked はその内の一つという位置づけです。
- World-Locked
- 現実の位置に重ねて表示
- Display-Locked
- ディスプレイ上に固定
- Body-Locked
- 視界の範囲内で遅延させて表示
参考文献
VRゲームプレイ「Robo Recall(ロボリコール)」vol.1 with Oculus
他のVR開発メモはこちら
他間違っている箇所がありましたらコメントにお願いします。