今回はOculus Questの開発ネタをやっていきます。
内容的にはOculus Rift Sなどにもそのまま応用できるかと思います。
VR開発の基本の基本、Oculus Touchコントローラーで物を掴み、物を投げるところまでやってみます。
先行研究
開発環境
Windows 10
Unity 2018.4.1f
Oculus Integration ver1.37
Oculus Quest
セットアップ
基本的なセットアップをしておきましょう。
こちらのブログ様がとてもわかりやすい解説記事を投稿なさっています。
Oculusの開発には「Oculus Integration」というアセットが必須です。必ずインポートしましょう。
細かい設定は上のブログを参考にしてみてください。
追記 2020/02/18
当ブログでもまとめました。
主要コンポーネント
物を掴んだり、投げる動作はOculus側でコンポーネントが用意されています。
そちらを使っていきましょう。
これらはインポートしたOculus Integrationの
Assets/Oculus/VR/Scriptsにあります。
OVR Grabber
こちらは物を掴む側、つまり手につけるコンポーネントになります。
OVR Grabbable
こちらは物を掴まれる側、つまりオブジェクト側につけるコンポーネントになります。
サンプルシーンの確認
Assets/SampleFramework/Usageに様々なサンプルシーンがあります。
物を掴むサンプルシーンはAvatarGrabになります。
学習や挙動の確認にとても有益です。見てみましょう。
実行してみるとこんな感じになります。
【追記】 2020/02/18
AvatarGrabシーンが削除されました。詳しくはこちら。
OVR Grabber
AvatarGrabのシーンにある、AvatarGrabberを見てみましょう。
OVR Grabberコンポーネントがついているのがわかります。
手にあたるオブジェクトにはこのコンポーネントが必要です。
(Rigitbodyも必要)
インスペクターパラメーター
GrabBegin
オブジェクトを掴むときのトリガーのしきい値です。(0~1の範囲)
この値が高ければ軽い押し込みで掴むことでき、
この値が低ければ深く押し込まないと掴むことができないようにできます。
GrabEnd
オブジェクトを放すときのトリガーのしきい値です。(0~1の範囲)
この値が低いほど、トリガーをしっかり離さないとオブジェクトは掴まれたままです。
Parent Hold Object
falseの場合、掴んだオブジェクトはFixedUpdateにて移動します。
Grip Transform
掴んだオブジェクトの移動先を指定します。おおよそ手の握った位置になります。
ここが設定されていないと掴もうとしても反応しません。(1敗)
Grab Volumes
掴む時の当たり判定、このコライダーが大きければ大きいほど掴める範囲が広くなります。
Controller
右手の場合はOVRInput.Controller.RTouch。
左手の場合はOVRInput.Controller.LTouchとしましょう。
Parent Transform
自身の親のTransformが入ります。
手動で設定されていない場合はScript側で勝手に設定されるのでさわる必要はありません。
他のプロパティ
OVRGrabbable grabbedObject
現在掴んでいるオブジェクトを取得
オブジェクトを取得といってもOVRGrabbableなので他のコンポーネントを取りたい場合はGetComponentする必要がある。
gameobject自体を取りたい場合は、grabbedObject.gameobjectで取れる。
OVR Grabbable
お次はCubeの方を見てみましょう。
OVR Grabbableコンポーネントがついているのがわかります。
掴むオブジェクトにはこのコンポーネントが必要です。
(RigitbodyとColliderも必要)
インスペクターパラメーター
Allow Offhand Grab
falseの場合掴めなくなります。
今は掴ませたくないオブジェクト、状況に応じて掴めたり掴めなかったりさせたい時に外部から変えるといいでしょう。
Snap Position
Trueの場合、掴まれたときオブジェクトの位置はSnap Offset(後述)と一致するように移動します。
剣や銃など、明確に持ってほしい箇所が決まっている時に設定します。
Snap Orientation
Trueの場合、掴まれたときオブジェクトの角度はSnap Offset(後述)と一致するように移動します。
こちらもPositiobnと同様、この辺りは別途記事で解説します。
Snap Offset
掴まれたときに移動するGrabberからの相対的な位置です。
何を言っているかわからない?この辺りは別途記事で解説します。
Grab Points
掴まれたときの接触点。Scriptを見てみるとGrabber側で掴むときの接触判定に使っているようです。
他のプロパティ
bool isGrabbed
つかまれているとtrueを返す
Grabberが現在掴んでいるオブジェクトを把握するのに使う
OVRGrabber grabbedBy
このオブジェクトを掴んでいるOVRGrabberを返す
掴んでいるのが右手か左手かを判別するのに使えるし、掴んでいる手の状態を取得できる
transform grabbedTransform
オブジェクトが掴まれた瞬間の位置を取得する
その場所になんらかのエフェクトを置いたりするのに使うのかも
rigitbody grabbedRigidbody
オブジェクトをつかむために使用されたコライダーのrigidbody
実際に掴めるオブジェクトを置いてみる
では実際に掴むことができるオブジェクトをテーブルの上に新しく作ってみましょう。
今回はユニティちゃんを使用します。
インスペクターはこんな感じです。
OVRGrabberのScriptの中では衝突判定にOnTriggerを使っているのでIsTriggerにチェックを入れたいところですが、別に入れなくても動作します。
サンプルシーンのキューブにもチェックは入っていません。
これだけで準備完了、実際に動かしてみましょう。
無事掴むことができ、投げることもできました。
まとめ
オブジェクトを掴むときはOVR Grabberコンポーネントを使う
手っ取り早く手を用意するのであれば、
Assets/Oculus/SampleFramework/Core/AvatarGrab/Prefabsにあるプレハブを使うのがおすすめ。
掴めるオブジェクトにはOVR Grabbableコンポーネントを使う
あとがき
プロパティやパラメータの説明は公式リファレンスやソースコードのコメント文から書き起こしました。
もしかしたら、変な訳になっているかもしれません、お気づきの点がございましたらコメントにお願いします。
公式リファレンスはこちらです。記事執筆時はバージョン1.37です。
OVR Grabber: https://developer.oculus.com/reference/unity/1.37/class_o_v_r_grabber/
OVR Grabbable: https://developer.oculus.com/reference/unity/1.37/class_o_v_r_grabbable/
他間違っている箇所がありましたらコメントにお願いします。