プログマのプログラマ日記

技術メモや自社サービスに関する記事を書いていく予定です。

Unity + Oculus Integrationで物をつかむ(その5:つかむときの手のポーズを設定)

Unity + Oculus Integrationを使ってコントローラやハンドトラッキングでオブジェクトをつかむまでの手順をStep by stepで説明します。
やっていることはOculus Integrationのサンプルシーン「HandGrabExamples」と同様ですが、これを0から組み立ててみてSceneを構成するコンポーネントの役割への理解を深めようという趣旨の記事です。

以下のステップで実装を進めていきます。

  • ルームスケールで動き回れるSceneを作成する手順
  • コントローラを表示できるようにする手順
  • 手を表示できるようにする手順
  • オブジェクトをつかめるようにする手順
  • オブジェクトをつかむときのポーズ(つかむ場所・手の形)を設定する手順(本記事)

2022/11/7: githubにプロジェクトを共有しました。
github.com

環境構築・プロジェクト作成

環境構築とプロジェクト作成の手順については、こちらの記事を参照してください。

rhikos-prgm.hatenablog.com

利用するコンポーネント

今回の記事で新たに使用するコンポーネントは以下の通りです。

HandGrabPose

オブジェクトをつかんだときのつかむ場所や手の形を設定するためのスクリプトです。
前回記事ではオブジェクトをつかむときに指がめり込んでしまってましたが、HandGrabPoseを設定することでこれを改善することができます。

指がめり込んでしまっている

HandGrabPoseの詳細は下記の「HandGrabPose」を参照。

Hand Grab | Oculus Developers

Sceneの実装手順

Sceneの作成

空のシーンを作成します。(Assets/Sandbox/HandGrab/Scenes/Scene4)
途中までは前の記事のScene3と同様に進めます。
(Scene3が作成済みならコピーしてリネームすれば良いです)

前回追加したHandGrabInteractableの削除

前回オブジェクトに追加したHandGrabInteractableは、もう使わなくなるため削除します。

Interactables
 +- GrabbableCapsule
     +- Visuals              
     +- HandGrabInteractable <- 削除する
     +- Audio

HandGrabPoseの記録(HandGrabPoseRecorderを使用)

HandGrabPoseは下図のようにJointAngleで指の関節の角度を決めますが、これを手動で設定するのは大変です。

JointAnglesで各指の関節の角度を設定

Oculus Integrationにはハンドトラッキングした手の形からHandGrabPoseを生成するためのツール(HandGrabPoseRecorder)が用意されているので、これを使っていくことにします。

HandGrabPoseRecorderの起動と設定

Oculus > Interaction > HandGrabPoseRecorderのメニューを選択するとHandGrabPoseRecorderのウィンドウが表示されます。
「Hand used for recording poses」の欄に、記録するときに使用する手を設定します。(左手で記録する場合はInputOVR/Hands/LeftHand、右手の場合はInputOVR/Hands/RightHand)
「GameObject to record the hand grab poses for」の欄に、HandGrabPoseを記録したいオブジェクトを設定します。
その他の項目はとりあえずデフォルトでも動作します。

HandGrabPoseRecorderのウィンドウ

記録

PlayModeに切り替えてヘッドセットを被ります。(要Oculus Link)
ハンドトラッキングでオブジェクトをつかむときの手の位置・形を調整します。
spaceキーを押すと、その時点のHandGrabPoseが記録されます。
spaceを押すたびに新しいHandGrabPose(下図の半透明な手の形)が記録されます。

HandGrabPoseを2つ設定

記録されたHandGrabPoseはオブジェクト配下に「HandGrabInteractable」の名前で追加されていきます。
ただし、これはPlayModeを抜けると消えてしまうため、後述の「保存」の手順でデータを残す必要があります。

保存

PlayModeを抜ける前にHandGrabPoseRecorderウィンドウの「SaveToCollection」ボタンを押します。
Assets/HandGrabInteractableDataCollection配下に

「[オブジェクト名]_HandGrabCollection.asset」

のような命名でデータが保存されるのを確認してください。

保存したデータをもとにポーズを復元

PlayModeを抜けます。
HandGrabPoseRecorderウィンドウの「LoadFromCollection」ボタンを押すと、記録したHandGrabPoseが復元されます。

指がめり込まないようにするための設定

上記の手順で、記録したHandGrabPoseの場所でオブジェクトをつかんでくれるようにはなるのですが、まだ指はオブジェクトにめり込んでしまいます。

つかむ場所は記録した場所になったが、指はオブジェクトにめり込んでしまう

これを解消するためには、HandGrabInteractorのHandGrabVisual経由で手の形を合成してあげる必要があります。

HandGrabVisual経由でHandVisualを合成するイメージ図。公式ページより引用:

具体的な手順は以下の通りです。

コントローラでオブジェクトをつかむときの設定

コントローラでオブジェクトをつかんだときに指がめり込まないように設定していきます。
※コントローラを使用しない場合は、この手順はスキップしても構いません。

InputOVR/ControllerHands/LeftControllerHand/ControllerHandInteractors/HandGrabInteractor/Visuals/HandGrabVisual(深い!)をアクティブにします。

HandGrabVisualのコンポーネントHandGrabStateVisualのSyntheticHandにInputOVR/ControllerHands/LeftHandSyntheticを設定します。

※Right側も同様の手順で設定します。

ハンドトラッキングでオブジェクトをつかむときの設定

ハンドトラッキングでオブジェクトをつかんだときに指がめり込まないように設定していきます。
※ハンドトラッキングを使用しない場合は、この手順はスキップしても構いません。

InputOVR/Hands/LeftHand/HandInteractorsLeft/HandGrabInteractor/Visuals/HandGrabVisualをアクティブにします。
InputOVR/Hands/LeftHandVisualを非アクティブにします。

HandGrabVisualのコンポーネントHandGrabStateVisualのSyntheticHandにInputOVR/Hands/LeftHandSyntheticを設定します。

※Right側も同様の手順で設定します。

動作確認

実行すると記録した通りのポーズでオブジェクトをつかむことができるようになります。

めり込んでない!

補足1:指の関節の角度の微調整

上の図をみると、まだちょっと親指がオブジェクトにめり込んでいるのが気になります。
HandGrabPoseRecorderでポーズを撮り直しても良いのですがシーンビューやインスペクタから指の関節の角度を調整することも可能です。

調整前。親指がめり込んでいる(赤丸のところ)が気になる。

関節部分(水色の丸のところ)をマウスでドラッグすると黄色くなる

そのままドラッグ移動すると関節の角度を調整できる

親指がめりこまなくなった(今度はちょっと離れてしまった...)

補足2:右手のポーズから左手のポーズを合成

右手でも左手でも同じようにオブジェクトをつかみたいというのは良くあるケースだと思います。
HandGrabInteractableの「Create Mirrored HandGrabInteractable」ボタンを押すと「HandGrabInteractable_mirror」が生成されます。
(反対側でもったときの鏡合わせのポーズが格納される)

参考サイト

公式:Oculusスタートガイド(Unity)
Get Started with Oculus in Unity | Oculus Developers

公式:入力データの概要
※サンプルシーンのInteractionRigOVR~prefab配下のコンポーネント群が何をやっているのか、ざっくり理解するための最適なドキュメントだと思います。
Inputs | Oculus Developers

公式:APIリファレンス
Reference