Raspberlyのブログ

Raspberlyのブログ

Unityネタをメインとした技術系ブログです。にゃんこ大戦争や日常なども。そろそろブログタイトル決めたい

【Oculus Quest開発メモ】VR空間内を歩き回る OVR PlayerController編 【Unity】

今回はOculus Questの開発ネタをやっていきます。
内容的にはOculus Rift Sなどにもそのまま応用できるかと思います。

 

VR開発の基本、空間内で自由に歩き回る方法について解説します。
VR空間での移動方法はいろいろありますが、今回はワープを使わない方法でやります。

 

 

8月29日追記

OculusIntegration1.40時点で、この記事の手順通りだとうまくいかない箇所があります。
解決次第追記します。

 

 

 

 

 

開発環境

Windows 10

Unity 2018.4.1f

Oculus Integration ver1.37

Oculus Quest

 

 

 

セットアップ

事前に前回の開発メモを読んでおくと理解がスムーズになると思いますのでまだの方はどうぞ。

raspberly.hateblo.jp

raspberly.hateblo.jp

 

 

 

 

 

サンプルシーンの確認

Assets/SampleFramework/Usageに様々なサンプルシーンがあります。
学習や挙動の確認にとても有益です。

今回の主要コンポーネントであるOVRCharacterControllerですが、
実はいろいろなシーンで使用されています

前回のDistanceGrabberのシーンでも使用されていました。

それだけ汎用性のある機能です。

 

 

 

 

主要コンポーネント

こちらもOculusの方で予めコンポーネントが用意されています。 

OVR Character Controller

VR空間で動き回るのに使用するコンポーネントです。

 

 

 

 

 

 

OVRPlayerController

このコンポーネントはUnity標準のCharacterControllerを使用します。
ただしRequireComponentで勝手にアタッチされるので特に気にする必要はないです。

f:id:Raspberly:20190629011930p:plain

インスペクターパラメーター

DistanceGrabberに負けず劣らずのパラメーター量です。

float Acceleration

 移動中の加速度

float Damping

 移動速度の減衰率、これの値が大きいほどすぐ止まる。

float BackAndSideDampen

 移動中に反対方向に移動した時の追加の減衰率。

float JumpForce

 ジャンプ中にキャラクターにかかる力。
実は定義されているだけで実装されているわけではありません。(後述)

float RotationAmount

 ゲームパッドを使用している時の回転速度。

float RotationRatchet

 キーボードを使用している時の回転速度。

bool SnapRotation

 スナップ回転を有効にするかどうか。
スナップ回転とは、方向転換時にプレイヤーを一定の角度ごとに回転させること。

f:id:Raspberly:20190629000450g:plain

f:id:Raspberly:20190629000516g:plain

上のgifがスナップ回転有効時の挙動、下のgifは無効時の挙動です。
スナップ回転は一見カクカクしているように見えますが、
プレイヤーのベクションを回避し、VR酔いを軽減する効果があります。

int FixedSpeedSteps

 直線移動で使用する固定速度。

bool HmdResetsY

 trueの場合、HMDポーズが再び中央に戻った時にプレイヤーコントローラーのヨーをリセットします。

bool HmdRotatesY

 trueの場合、OVRCameraRigの回転に合わせて移動方向を変更します。
つまりHMDの向きがそのままCharacterControllerに反映されます。
より直観的な動きが可能になります。

以下のgifは常に前進している様子です。
前進しているだけですが顔(HMD)の向きを変えるだけで方向転換しています。

f:id:Raspberly:20190629015808g:plain



float GravityModifier

 重力の設定RigidbodyのGravityと同じです。0にすると落下しません。

bool useProfileData

 プレイヤーの身長を使用するかどうか

float CameraHeight

 シーン内におけるカメラの高さの設定。
「低い天井の場所は移動させないなど」の制限を与えることができます

bool Teleported

 プレイヤーがテレポートするときにTrueになります。
外部からの参照用のようです

bool EnableLinearMovement

 ユーザー入力を直線的にする

bool EnableRotation

 ユーザー入力を回転に適応する

bool RotationEitherThumbstick

 回転を2-Axisなものにするかどうかデフォルトだとオンになります 。

 

 

 

 

 

 

 

実際に歩いてみる

サンプルシーンを動かせばすぐに歩き回れますが、
新しいシーンを作って一からセットアップしてみます。

 

まずはNew Sceneで新しいシーンを作ります。
何もないので、地面となるPlaneを作りましょう。
また、MainCameraは必要ないので消しておきます。

f:id:Raspberly:20190628230756p:plain

 

 

プレハブの準備

Asset/Oculus/VR/Prefabsの中にOVRPlayerControllerがありますので、
これをシーン内に配置します。

f:id:Raspberly:20190628234310p:plain

 

これだけで準備OK!
シーン内を動き回ることができます。

f:id:Raspberly:20190629000335g:plain



 

 

 

 

手を出したい

動き回れるからには手も表示したいものです。実際にやってみましょう。
今回はDistanceGrabbableを使ってみます。OVRGrabberも同様の手順です

f:id:Raspberly:20190629001915p:plain

Assets/Oculus/SampleFramework/Core/DistanceGrab/Prefabsにある
DistanceGrabプレハブを右手左手共にシーンに配置します。

OVRGrabberを使用したい時はAssets/Oculus/SampleFramework/Core/AvatarGrab/Prefabsにあるプレハブを使いましょう。

シーン内のHierarchyビューはこんな感じになります。

f:id:Raspberly:20190629002251p:plain



このまま実行したいところですが、手の方に親を設定してあげる必要があります。
各種Grabのインスペクターを見てみましょう。

注目すべきはParentTransformPlayerです。

f:id:Raspberly:20190629002514p:plain

ParentTransformには、OVRPlayerControllerの子オブジェクトであるOVRCameraRigをアタッチします。
PlayerにはOVRPlayerControllerをそのままアタッチします。

 

ここで実はもう一つやることがあります、ちょっとだけ詰まった個所です。
OVRPlayerControllerのHmd RotateYのチェックを外しておきましょう。
これをしないと正しく追従しないことがありました。

f:id:Raspberly:20190629010255p:plain

 

これで手が表示され、Playerの移動や回転に合わせて追従します。
間違えやすい点として、GrabberプレハブはPlayerの子オブジェクトにしない点に注意しましょう。

f:id:Raspberly:20190629011751g:plain

 

 

 

 

 

 

ジャンプしたい

コンポーネントの説明でもしましたが、
デフォルトではジャンプ機能は定義されていますが、実装はされていません。
実際にOVRPlayerController.csを見てみると、ジャンプ関数がこのようになっています。

f:id:Raspberly:20190629003237p:plain

この関数はどこからも呼ばれておらず、サマリーには「手動で有効にしましょう」と書いてあります。

なので実際に以下のようなコードをOVRPlayerController.cs内あるいは独自スクリプト内に追加しましょう。

OVRPlayerController.csに追加する場合はUpdateController()UpdateMovement()内に記述するのがよさそうです。

独自スクリプトの場合はUpdate()でいいでしょう。

 

ここまでやればジャンプできるようになります。

f:id:Raspberly:20190629010510g:plain


JumpForceを大きくすると瞬時に飛び上がるようになり、
Gravityを小さくするとふわふわと降りるようにできたりもします。

f:id:Raspberly:20190629010531g:plain



 

 

 

 

 

 

 

 

他のアプローチ

@nkjzmさんが詳しく解説しています。
OVRInputから、Touchコントローラーの入力を取得することができるので、
そこから作りたいコンテンツに合わせた最適な移動システムを作ることができます。

qiita.com

 

 

 

 

 

まとめ

VR空間で歩き回りたい時はOVRPlayerControllerを使うとよい

手っ取り早く用意するのであれば、Asset/Oculus/VR/Prefabsにあるプレハブを使うのがおすすめ。

 

 

 

 

おまけ

 

追記:Oculus Linkがあるのならそちらの方がよいです。

 

私は開発環境にALVRを導入しています。
Oculus Rift sの場合はそのままエディタで動作確認ができますが、
Oculus Questの場合はいちいちビルドしなければならずかなり大変です


ALVRなら、Rift sのようにUnity上で実行できSceneビューからも客観的に確認できます。

f:id:Raspberly:20191008013547g:plain

ALVRについてはこちらでも最初の方で簡単に紹介しています。

 

 

 

 

 

公式リファレンスはこちらです。記事執筆時はバージョン1.37です。

https://developer.oculus.com/reference/unity/1.37/class_o_v_r_player_controller/

 

他間違っている箇所、不明な点、わかりにくい点がありましたらコメントにお願いします。