今回はOculus Questの開発ネタをやっていきます。
内容的にはOculus Rift Sなどにもそのまま応用できるかと思います。
VR開発の基本、空間内で自由に歩き回る方法について解説します。
VR空間での移動方法はいろいろありますが、今回はワープを使わない方法でやります。
8月29日追記
OculusIntegration1.40時点で、この記事の手順通りだとうまくいかない箇所があります。
解決次第追記します。
- 開発環境
- セットアップ
- サンプルシーンの確認
- 主要コンポーネント
- OVRPlayerController
- インスペクターパラメーター
- float Acceleration
- float Damping
- float BackAndSideDampen
- float JumpForce
- float RotationAmount
- float RotationRatchet
- bool SnapRotation
- int FixedSpeedSteps
- bool HmdResetsY
- bool HmdRotatesY
- float GravityModifier
- bool useProfileData
- float CameraHeight
- bool Teleported
- bool EnableLinearMovement
- bool EnableRotation
- bool RotationEitherThumbstick
- インスペクターパラメーター
- 実際に歩いてみる
- 他のアプローチ
- まとめ
- おまけ
開発環境
Windows 10
Unity 2018.4.1f
Oculus Integration ver1.37
Oculus Quest
セットアップ
事前に前回の開発メモを読んでおくと理解がスムーズになると思いますのでまだの方はどうぞ。
サンプルシーンの確認
Assets/SampleFramework/Usageに様々なサンプルシーンがあります。
学習や挙動の確認にとても有益です。
今回の主要コンポーネントであるOVRCharacterControllerですが、
実はいろいろなシーンで使用されています。
前回のDistanceGrabberのシーンでも使用されていました。
それだけ汎用性のある機能です。
主要コンポーネント
こちらもOculusの方で予めコンポーネントが用意されています。
OVR Character Controller
OVRPlayerController
このコンポーネントはUnity標準のCharacterControllerを使用します。
ただしRequireComponentで勝手にアタッチされるので特に気にする必要はないです。
インスペクターパラメーター
DistanceGrabberに負けず劣らずのパラメーター量です。
float Acceleration
移動中の加速度
float Damping
移動速度の減衰率、これの値が大きいほどすぐ止まる。
float BackAndSideDampen
移動中に反対方向に移動した時の追加の減衰率。
float JumpForce
ジャンプ中にキャラクターにかかる力。
実は定義されているだけで実装されているわけではありません。(後述)
float RotationAmount
ゲームパッドを使用している時の回転速度。
float RotationRatchet
キーボードを使用している時の回転速度。
bool SnapRotation
スナップ回転を有効にするかどうか。
スナップ回転とは、方向転換時にプレイヤーを一定の角度ごとに回転させること。
上のgifがスナップ回転有効時の挙動、下のgifは無効時の挙動です。
スナップ回転は一見カクカクしているように見えますが、
プレイヤーのベクションを回避し、VR酔いを軽減する効果があります。
int FixedSpeedSteps
直線移動で使用する固定速度。
bool HmdResetsY
trueの場合、HMDポーズが再び中央に戻った時にプレイヤーコントローラーのヨーをリセットします。
bool HmdRotatesY
trueの場合、OVRCameraRigの回転に合わせて移動方向を変更します。
つまりHMDの向きがそのままCharacterControllerに反映されます。
より直観的な動きが可能になります。
以下のgifは常に前進している様子です。
前進しているだけですが顔(HMD)の向きを変えるだけで方向転換しています。
float GravityModifier
重力の設定RigidbodyのGravityと同じです。0にすると落下しません。
bool useProfileData
プレイヤーの身長を使用するかどうか
float CameraHeight
シーン内におけるカメラの高さの設定。
「低い天井の場所は移動させないなど」の制限を与えることができます
bool Teleported
プレイヤーがテレポートするときにTrueになります。
外部からの参照用のようです
bool EnableLinearMovement
ユーザー入力を直線的にする
bool EnableRotation
ユーザー入力を回転に適応する
bool RotationEitherThumbstick
回転を2-Axisなものにするかどうかデフォルトだとオンになります 。
実際に歩いてみる
サンプルシーンを動かせばすぐに歩き回れますが、
新しいシーンを作って一からセットアップしてみます。
まずはNew Sceneで新しいシーンを作ります。
何もないので、地面となるPlaneを作りましょう。
また、MainCameraは必要ないので消しておきます。
プレハブの準備
Asset/Oculus/VR/Prefabsの中にOVRPlayerControllerがありますので、
これをシーン内に配置します。
これだけで準備OK!
シーン内を動き回ることができます。
手を出したい
動き回れるからには手も表示したいものです。実際にやってみましょう。
今回はDistanceGrabbableを使ってみます。OVRGrabberも同様の手順です
Assets/Oculus/SampleFramework/Core/DistanceGrab/Prefabsにある
DistanceGrabプレハブを右手左手共にシーンに配置します。
OVRGrabberを使用したい時はAssets/Oculus/SampleFramework/Core/AvatarGrab/Prefabsにあるプレハブを使いましょう。
シーン内のHierarchyビューはこんな感じになります。
このまま実行したいところですが、手の方に親を設定してあげる必要があります。
各種Grabのインスペクターを見てみましょう。
注目すべきはParentTransformとPlayerです。
ParentTransformには、OVRPlayerControllerの子オブジェクトであるOVRCameraRigをアタッチします。
PlayerにはOVRPlayerControllerをそのままアタッチします。
ここで実はもう一つやることがあります、ちょっとだけ詰まった個所です。
OVRPlayerControllerのHmd RotateYのチェックを外しておきましょう。
これをしないと正しく追従しないことがありました。
これで手が表示され、Playerの移動や回転に合わせて追従します。
間違えやすい点として、GrabberプレハブはPlayerの子オブジェクトにしない点に注意しましょう。
ジャンプしたい
コンポーネントの説明でもしましたが、
デフォルトではジャンプ機能は定義されていますが、実装はされていません。
実際にOVRPlayerController.csを見てみると、ジャンプ関数がこのようになっています。
この関数はどこからも呼ばれておらず、サマリーには「手動で有効にしましょう」と書いてあります。
なので実際に以下のようなコードをOVRPlayerController.cs内あるいは独自スクリプト内に追加しましょう。
OVRPlayerController.csに追加する場合はUpdateController()やUpdateMovement()内に記述するのがよさそうです。
独自スクリプトの場合はUpdate()でいいでしょう。
ここまでやればジャンプできるようになります。
JumpForceを大きくすると瞬時に飛び上がるようになり、
Gravityを小さくするとふわふわと降りるようにできたりもします。
他のアプローチ
@nkjzmさんが詳しく解説しています。
OVRInputから、Touchコントローラーの入力を取得することができるので、
そこから作りたいコンテンツに合わせた最適な移動システムを作ることができます。
まとめ
VR空間で歩き回りたい時はOVRPlayerControllerを使うとよい
手っ取り早く用意するのであれば、Asset/Oculus/VR/Prefabsにあるプレハブを使うのがおすすめ。
おまけ
追記:Oculus Linkがあるのならそちらの方がよいです。
私は開発環境にALVRを導入しています。
Oculus Rift sの場合はそのままエディタで動作確認ができますが、
Oculus Questの場合はいちいちビルドしなければならずかなり大変です。
ALVRなら、Rift sのようにUnity上で実行できSceneビューからも客観的に確認できます。
ALVRについてはこちらでも最初の方で簡単に紹介しています。
公式リファレンスはこちらです。記事執筆時はバージョン1.37です。
https://developer.oculus.com/reference/unity/1.37/class_o_v_r_player_controller/
他間違っている箇所、不明な点、わかりにくい点がありましたらコメントにお願いします。