Raspberlyのブログ

Raspberlyのブログ

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

【Oculus Quest開発メモ】物を掴む、物を投げる OVR Grabber & Grabbable編【Unity】

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

VR開発の基本の基本、Oculus Touchコントローラーで物を掴み、物を投げるところまでやってみます。

f:id:Raspberly:20190608234840p:plain



 

 

 

 

先行研究

note.mu

 

開発環境

Windows 10

Unity 2018.4.1f

Oculus Integration ver1.37

Oculus Quest

 

 

 

セットアップ

基本的なセットアップをしておきましょう。
こちらのブログ様がとてもわかりやすい解説記事を投稿なさっています。

cycling.hateblo.jp

 

Oculusの開発には「Oculus Integration」というアセットが必須です。必ずインポートしましょう。

細かい設定は上のブログを参考にしてみてください。

 

 

 

 

主要コンポーネント

物を掴んだり、投げる動作はOculus側でコンポーネントが用意されています。
そちらを使っていきましょう。

これらはインポートしたOculus Integrationの
Assets/Oculus/VR/Scriptsにあります。

OVR Grabber

こちらは物を掴む側、つまり手につけるコンポーネントになります。

OVR Grabbable

こちらは物を掴まれる側、つまりオブジェクト側につけるコンポーネントになります。

 

 

 

サンプルシーンの確認

Assets/SampleFramework/Usageに様々なサンプルシーンがあります。
物を掴むサンプルシーンはAvatarGrabになります。
学習や挙動の確認にとても有益です。見てみましょう。

f:id:Raspberly:20190608164841p:plain

 

実行してみるとこんな感じになります。

f:id:Raspberly:20190608180414g:plain

 

 

 

 

 

OVR Grabber

AvatarGrabのシーンにある、AvatarGrabberを見てみましょう。

f:id:Raspberly:20190608213450p:plain

f:id:Raspberly:20190608215714p:plain


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の方を見てみましょう。

f:id:Raspberly:20190608224838p:plain

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

 

 

 

 

実際に掴めるオブジェクトを置いてみる

では実際に掴むことができるオブジェクトをテーブルの上に新しく作ってみましょう。
今回はユニティちゃんを使用します。

f:id:Raspberly:20190608231347p:plain

 

インスペクターはこんな感じです。
OVRGrabberのScriptの中では衝突判定にOnTriggerを使っているのでIsTriggerにチェックを入れたいところですが、別に入れなくても動作します。
サンプルシーンのキューブにもチェックは入っていません。

f:id:Raspberly:20190608231544p:plain


これだけで準備完了、実際に動かしてみましょう。
無事掴むことができ、投げることもできました。

f:id:Raspberly:20190608233843g:plain

 

 

 

 

まとめ

オブジェクトを掴むときは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/

 

 

他間違っている箇所がありましたらコメントにお願いします。