今回はOculus Questの開発ネタをやっていきます。
内容的にはOculus Rift Sなどにもそのまま応用できるかと思います。
OVR Grabberなどで物を掴んだ時に、位置と角度を固定する方法について紹介します。
本記事は過去の記事の追記バージョンになります。
前回の記事にこのようなフィードバックをいただきました。
【Oculus Quest開発メモ】物を掴むとき位置と角度を固定する Snap Offset編【Unity】 - Raspberlyのブログ https://t.co/lNUrCOd65o
— むーう (@warori106) September 4, 2019
“掴みたいオブジェクトのレンダラーの座標、角度を調整する“ってあるけどどう調整するの...??
改めて見直すと完全に説明不足でした。本当に申し訳ありません。
前回をベースにGifと解説を増やしてお送りいたします。SnapOffsetをNullにする方法です。
開発環境
Windows 10
Unity 2018.4.5f
Oculus Integration ver1.40
Oculus Quest
ALVR
※ALVRだと、物を掴んだ時に人差し指が正常にアニメーションしないことがあります。
本記事の画像やGifでもたびたびありますが、機能的には何も問題ありません。
セットアップ
開発環境を整えていない方は先にこちらをどうぞ。
参考
Unity で Android アプリをビルドするには - フレームシンセシス
Unity+Oculus Quest 開発メモ - フレームシンセシス
サンプルシーンの確認+準備
基本的な掴む投げる動作を学ぶことができるAvatarGrabシーンを使います。
OVR Grabber、DistanceGrabber共に動くのでDistanceGrabシーンでも特に問題はありません。
【追記】 2020/02/18
AvatarGrabシーンが削除されました。詳しくはこちら。
手を出す
ALVRでやる場合はこちらを参考に手を用意しておきましょう。
CustomHandプレハブをシーンに置くだけです。
Hand.csの修正も忘れずに
3Dモデルの用意
前回に引き続き、刀と銃のアセットを使用します。
自前で3Dモデルをお持ちでしたらそちらで構いません。
刀アセット Wakizashi
高品質な刀です。AssetStoreまとめさんでも紹介されていました。
ハンドガンアセット
弾丸やマガジンも含まれたハンドガンのアセットです。
3Dモデルの配置
まずステージ内に先ほどインポートした、刀と銃を配置します。
その前に、目の前のテーブルが少し狭いので邪魔なオブジェクトは予め非アクティブにしておきましょう。
インスペクターからチェックを外すだけです。
刀
Wakizashiプレハブをシーンに置きます。
この時、空のGameObjectを作りその中にWakizashiプレハブを子オブジェクトとして登録しておきます。
こうすると後々楽になります。今回はKatanaという名前をつけました。
そのままだと垂直に置かれるため、PositionやRotationを変えて寝かせるといいでしょう。
ついでに、Wakizashiプレハブの子オブジェクトにある_Collidersは非アクティブにしておきます。
銃
Handgun_M1911A_Blackプレハブをシーンに置きます。
この3Dモデルにはマガジン(弾倉)がついていません。
同じフォルダ内にあるM11911A_Magazine_Blackを子オブジェクトにしてあげるといい感じになります。
ただし、そのままシーンに置くとスケール感がまったく合わないためこちらもTransformを調整します。
コンポーネントのアタッチ
配置しましたら、必要なコンポーネントをアタッチしていきます。
必要なのはOVR Grabbableコンポーネント、Rigidbody、Colliderです。
刀
Katanaオブジェクトのインスペクターを以下のようにします。
銃
Handgunプレハブに直接アタッチしていきます。
刀銃共にコライダーは適当につけています。細かい調整はSnap設定後にしましょう。
これで掴むことができます。
ここまではOVR GrabberとOVR Grabbableの復習を兼ねています。
この状態だと、オブジェクトのどこでも掴むことができるので、刀の刀身をそのまま掴めます。
Snapの設定
ここからが本題です。Snap機能を追加します。
今回は刀の方をメインで行います。銃も同じ手順で設定できます。
OVR Grabbableの設定
まずは、刀、銃共にOVR GrabbableのSnap PositionとSnap Orientationにチェックを入れます。
Snap OffsetはNullのままです。
次にUnityエディターのHandle PositionをPivotにしておきます。(標準だとPivotのはず)
ここはボタンになっていて切り替えることができます。
Colldierの設定
今までは親オブジェクトにColliderを付けていましたが、3Dモデルに沿った当たり判定を付けたいため、
親ではなくMeshRendererのついた子オブジェクトにColliderをつけます。(最初からこうしてもよかったかも)
KatanaオブジェクトのBoxColliderを無効化、あるいは削除します。
WakizashプレハブにBoxColliderをアタッチします。この時パラメータも自動でいい感じに設定してくれます。
また、最初からついているRigidbodyを削除します。最終的に↓のような感じ。
最後にKatanaオブジェクトのOVR GrabbableにあるGrabPointsにWakizashiプレハブのBoxColliderを紐づけます。
Snapする位置と角度(刀の場合)
Katanaオブジェクトを選択してシーンビューを見てみましょう。
XYZの矢印が表示されます(この矢印のことをGizmo(ギズモ)といいます)
ここがKatanaオブジェクトの原点座標です。
Katanaの場合、鍔の部分が原点になっていますね。
先ほど、OVR GrabbableのSnap OffsetをNullのままにしましたが、
ここがNullだとSnapしたときの位置と角度はオブジェクトの原点座標と同じになります。
試しにこの状態のまま動かしてみると、どこを掴んでも鍔の部分にSnapされているのがわかります。
3Dモデルの位置調整
刀の場合、MeshRendererコンポーネントがあるのはWakizashiプレハブです。
そのため、Wakizashiプレハブの座標を掴ませたい位置と角度に合わせて移動してあげます。
何度か実行してテストしながら、手にピッタリ合った位置と角度を見つけましょう。
効率的な調整方法
OculusQuestで毎回ビルドしながら位置角度調節するのはなかなか苦行です。
できることならRift SかALVRを使い、Unityエディター上で調整しましょう。その方が手っ取り早いです。
以下やり方を紹介
まず、エディター上で起動し、手に持ったところで一時停止します。
そうしたら、シーンビューでWakizashiプレハブをいい感じの位置と角度に調整します。
(キーボードのQWERTキーで、編集モードを変えていくとスムーズに調整できます)
無事調整できたら、この時点のWakizashiプレハブのTransform値をコピーします。
プレイモード解除後に値はリセットされますが、そこに先ほどコピーした値を上書きします。
これで手にフィットした形に、Wakizashiプレハブの位置と角度が設定されました。
最後にWakizashiプレハブのTransformは変えずに、親であるKatanaオブジェクトの位置を調整して完成です。
刀のどこを掴んでも、掴んだ瞬間位置と角度が矯正されます。
銃オブジェクトも同様に設定できます。
これで、掴んだ時の位置と角度を固定できるようになりました。
まとめ
SnapOffsetはnullのまま、子オブジェクトの3Dモデルの位置を調整する
別の方法について
とても使いにくいことで評判のSnap Offsetですが、@udo_nbaさんが大変わかりやすい記事を投稿しています。
作るのが面倒なSnapOffsetを簡単に作る方法を解説しています。
こちらも参考にしてみてください。
わかりにくい所、間違っている箇所がありましたらコメントにお願いします。
特に、「ここがよくわからん」「それどうやってるの?」「そんな項目ないんだが」など
詰まる箇所がありましたらドシドシコメントに書き込んでください。よろしくお願いします。