Unityのジェスチャーコントロール


データ使用の免責事項: ハンドトラッキングのサポートを有効にすると、アプリから特定のユーザーデータ(ユーザーの手の推定サイズや手のポーズデータなど)にアクセスできます。このデータは、アプリ内でハンドトラッキングを有効にする目的でのみ使用でき、他の目的での使用は明示的に禁止されています。


ハンドトラッキング機能を使うと、Oculus Questデバイスの入力メソッドとして手を使用できます。手や指の関節の動きを完全にトラッキングすることで、新しいプレゼンス感覚がもたらされ、ソーシャルエンゲージメントが高まり、より自然なインタラクションが実現します。つまむ、放す、つまんだままにするなど、単純な手のジェスチャーにより、手でオブジェクトの操作を実行することができます。

ハンドトラッキング機能を使えば、手とコントローラーのどちらでも操作できます。手を使用する場合、標準のコントローラーカーソルのように動作するレーザーカーソルポインターを手のポーズで動かします。カーソルポインターを使用して、アプリレベルのイベントロジックのハイライト、選択、クリック、書き込みが行えます。

ハンドトラッキングはTouchコントローラーを補完するものであり、高い精度が求められるゲームやクリエイティブツールなど、あらゆるシナリオでコントローラーに置き換わるものではありません手のサポートをオプトインする場合、アプリはOculusストアで承認されるよう、ハンドトラッキング特有の付加的な技術要件を満たす必要があります。アプリをOculusストアに提出するには、アプリはコントローラーとハンドトラッキングを一緒にサポートしなければなりません。

バーチャルリアリティにおける手の使い方のガイドラインを詳しく説明している、ハンドトラッキングデザインについてのさまざまなリソースと、OC6動画プレゼンテーション「ハンドトラッキング技術詳細: テクノロジー、デザイン、およびエクスペリエンス」もご確認ください。

アプリで手をレンダリングする

アプリでは、他のインプットデバイスと同じ方法で手をレンダリングします。以下のセクションで、アプリで手をレンダリングする基本的な方法について説明します。

: Oculus QuestとOculus Linkを使用する場合、PC上でのハンドトラッキングの使用はUnityエディターでサポートされています。この機能は、Oculus Quest開発者の反復時間短縮のため、Unityエディターでのみサポートされています。

ハンドトラッキングを有効にしAndroidマニフェストアクセス許可を理解する

OVRManagerは、コントローラーのみ、コントローラーと手、手のみなど、Unityでハンドトラッキングを有効にするさまざまなオプションを表示します。ハンドトラッキングを有効にするすべてのオプションのため、Oculusは<uses-persmission><uses-feature>要素をAndroidManifest.xmlファイルに自動的に追加します。アプリがコントローラーのみをサポートする場合、マニフェストファイルに何も要素を追加しません。

  • <uses-permission>要素には、android:name="com.oculus.permission.HAND_TRACKING"属性が含まれます。

    <uses-permission android:name="com.oculus.permission.HAND_TRACKING" />

  • <uses-feature>要素には、ブーリアン値のandroid:name="oculus.software.handtracking"属性とandroid:required属性の2つが含まれます。アプリがコントローラーと手をサポートする場合、android:required"false"に設定されます。この設定では、アプリが手を認識した場合は手を使用し、手が認識されない場合はコントローラーで機能します。アプリが[Hands Only (手のみ)]をサポートする場合、android:required"true"に設定されます。

    <uses-feature android:name="oculus.software.handtracking" android:required="false" />

ヒント:Unityでハンドトラッキングを有効にする場合、Androidマニフェストファイルを手動で更新する必要はありません。

Unityからハンドトラッキングを設定する:

  1. 新しいシーンを作成するか、プロジェクトから既存のシーンを開きます。
  2. Oculus/VR/Prefabsフォルダーから、OVRCameraRig prefabをシーンにドラッグします。シーンにOVRCameraRigが既に存在している場合は、この手順はスキップします。
  3. [Hierarchy (階層)]ビューから、[OVRCameraRig]を選択します。
  4. [OVR Manager][Inspector (インスペクター)]ビューで[Quest]セクションに移動し、[Hand Tracking Support (ハンドトラッキングサポート)]のリストから[Controllers and Hands (コントローラーと手)]を選択します。
  5. Unityバージョン2017.4.xの場合は、[Oculus] > [Tools (ツール)] > [Create store-compatible AndroidManifest.xml (ストア対応AndroidManifest.xmlを作成)]に移動します。この追加手順により、現在構成されているハンドトラッキングアクセス許可でAndroidManifest.xmlファイルが生成されます。設定を変更する場合は、この手順を繰り返して新しいAndroidManifest.xmlを生成します。

: [Hands Only (手のみ)]オプションは、開発者実験でのみ利用できます。アプリをOculusストアに提出するには、アプリはコントローラーとハンドトラッキングの両方をサポートしていなければなりません。

デバイス上でハンドトラッキングを有効にする

仮想環境で手を使用するには、ユーザーがOculus Quest上でハンドトラッキング機能を有効にする必要があります。

  1. Oculus Questで、[Settings(設定)] > [Device(デバイス)]に移動します。
  2. トグルボタンをスライドして[ハンドトラッキング]を有効にします。
  3. 手とコントローラーを自動で切り替えられるようにするには、トグルボタンをスライドして[Auto Enable Hands or Controllers (手またはコントローラーの自動有効化)]を有効にします。

手をシーンに追加する

OVRHandPrefab prefabは手をインプットデバイスとして実装します。

  1. [Hierarchy(階層)]ビューから、[OVRCameraRig] > [TrackingSpace]を展開します。
  2. Oculus/VR/Prefabsフォルダーから、OVRHandPrefab prefabをLeftHandAnchorにドラッグします。これは、TrackingSpaceの下にあります。
  3. 手順2を繰り返して、OVRHandPrefab prefabをRightHandAnchorにドラッグします。
  4. LeftHandAnchorで、OVRHandPrefabを選択し、[Inspector (インスペクター)]ビューで設定を開きます。
  5. [OVRHand][OVRSkeleton][OVRMesh]の下で、左手タイプを選択します。
  6. 手順4と5を繰り返して、RightHandAnchorを右手タイプに設定します。

OVRHandPrefabが各ハンドアンカーに追加され、利き手を設定できたら、手をインプットデバイスとして使用できるようになります。

OVRHandPrefabを構成する

手のレンダリングやアプリ内でのオブジェクトの操作に影響する、いくつかの拡張レベル設定があります。

それらの設定について以下のセクションで説明します。

骨組みとメッシュデータを取得する

OVRメッシュレンダラーは、OVR骨組みとOVRメッシュから返されるデータを組み合わせることにより、手をレンダリングします。

  • OVRHandPrefab prefabを選択して、以下の設定を行います。
    • OVR骨組みは、骨組みバインドポーズ、骨格階層、カプセルコライダーデータなどのデータを提供します。

      骨組みタイプリストで、データを取得する手を選択します。例えば、左手などです。

    • OVRメッシュは、Oculusランタイムから指定された3Dアセットを読み込んで、それをUnityEngine.Meshとしてレンダリングします。メッシュは、頂点、uv、法線、骨格重量などの属性により構成されます。

      メッシュタイプリストで、データを取得する手を選択します。例えば、左手などです。

    • OVRメッシュレンダラーは、OVR骨組みとOVRメッシュから返されるデータを組み合わせることにより、手のアニメーション3Dモデルを生成します。

      [OVR Mesh Renderer(OVRメッシュレンダラー)]チェックボックスが選択されていることを確認してください。

ルートポーズを更新する

OVRCameraRigで左または右のハンドアンカーにOVRHandPrefabが関連付けられているなら、[Update Root Pose(ルートポーズの更新)]チェックボックスにはチェックを付けず、ハンドアンカーにより、トラッキングスペースで手が適切に位置付けられるようにします。

OVRHandPrefabをOVRCameraRigとは独立して使用する場合は、[Update Root Pose(ルートポーズの更新)]チェックボックスを選択し、指と骨格だけでなく手の実際のルートが正しく更新されるようにします。

ハンドモデルルートスケールを有効にする

ユニフォームスケールをリファレンスハンドモデルと比較することで、ユーザーの手のサイズの推定値を得ることができます。デフォルトでは、リファレンスハンドモデルのスケールは100%(1.0)に設定されています。スケーリングを有効にすることにより、ハンドモデルサイズは、ユーザーの実際の手のサイズに基づいてスケールが調整されます。ハンドスケールは随時変更されるため、実行時のレンダリングとインタラクションのために手のスケールを調整するようおすすめします。

  1. [Hierarchy(階層)]ウィンドウで、OVRHandPrefab prefabを選択します。
  2. [Inspector(インスペクター)]ウィンドウの[OVR Skeleton (Script)(OVR骨組み(スクリプト))]の下で、[Update Root Scale(ルートスケールの更新)]チェックボックスを選択します。

注:デフォルトのリファレンスハンドサイズを使用する場合、このチェックボックスはチェックを外したままにします。

物理カプセルを追加する

手の骨格の体積を表す物理カプセルを追加します。この機能は、物理オブジェクトとのインタラクションをトリガーしたり、物理システム内の他の剛体との衝突イベントを生成するために使用します。

  1. [Hierarchy(階層)]ウィンドウで、OVRHandPrefab prefabを選択します。
  2. [Inspector(インスペクター)]ウィンドウの[OVR Skeleton (Script)(OVR骨組み(スクリプト))]の下で、[Update Root Scale(ルートスケールの更新)]チェックボックスを選択します。

デバッグワイヤーフレーム骨組みのレンダリングを有効にする

ビジュアルデバッグを支援するため、ワイヤーフレーム直線により手の骨格をレンダリングすることができます。この機能は、開発中に手を視覚的にデバッグするために使用します。

  1. [Hierarchy(階層)]ウィンドウで、OVRHandPrefab prefabを選択します。
  2. [Inspector(インスペクター)]ウィンドウで、[OVR Skeleton Renderer(OVR骨組みレンダラー)]チェックボックスを選択します。

スキンマテリアルをカスタマイズする

デフォルトのハンドモデルの視覚的外観を変更するには、カスタマイズしたスキンマテリアルを用意します。新しいマテリアルを作成する方法について詳しくは、Unity開発者ガイドの「マテリアルの作成と使用」をご覧ください。

  1. [Hierarchy(階層)]ウィンドウで、OVRHandPrefab prefabを選択します。
  2. [Inspector(インスペクター)]ウィンドウで、[Skinned Mesh Renderer(スキンメッシュレンダラー)]チェックボックスが選択されていることを確認してください。
  3. [Materials(マテリアル)]の下の[Element 0(エレメント0)]で、使用するマテリアルをドラッグします。

カスタマイズしたメッシュを使用する

自分の選んだ手をレンダリングするには、独自のカスタマイズ済みメッシュを使用します。これは、既製の骨組みによって駆動されるカスタム骨組みをマッピングすることにより行われます。使用例については、HandTest_Customシーンを参照してください。そこでは、新しいOVRCustomHandPrefab_LOVRCustomHandPrefab_Rのprefab、新しいOVRCustomSkeleton.csスクリプトが使用されています。

アプリに手を統合する

OVRHandPrefabの設定を構成したら、アプリで手のレンダリングが開始されます。このセクションでは、手をアプリに統合することにより、臨場感あふれる対話式アプリをビルドするのに役立つスクリプトやAPIのいくつかについて説明します。

骨格IDを理解する

OVRSkeleton.csには、骨組みの各骨格をユニークに識別するための骨格IDすべてのリストが含まれています。骨格IDは、ジェスチャーの検出、ジェスチャーの信頼性の計算、特定の骨格のターゲット設定、物理システム内の衝突イベントのトリガーなど、アプリレベルのインタラクションを実現するために使用します。

Invalid          = -1
Hand_Start       = 0
Hand_WristRoot   = Hand_Start + 0 // root frame of the hand, where the wrist is located
Hand_ForearmStub = Hand_Start + 1 // frame for user's forearm
Hand_Thumb0      = Hand_Start + 2 // thumb trapezium bone
Hand_Thumb1      = Hand_Start + 3 // thumb metacarpal bone
Hand_Thumb2      = Hand_Start + 4 // thumb proximal phalange bone
Hand_Thumb3      = Hand_Start + 5 // thumb distal phalange bone
Hand_Index1      = Hand_Start + 6 // index proximal phalange bone
Hand_Index2      = Hand_Start + 7 // index intermediate phalange bone
Hand_Index3      = Hand_Start + 8 // index distal phalange bone
Hand_Middle1     = Hand_Start + 9 // middle proximal phalange bone
Hand_Middle2     = Hand_Start + 10 // middle intermediate phalange bone
Hand_Middle3     = Hand_Start + 11 // middle distal phalange bone
Hand_Ring1       = Hand_Start + 12 // ring proximal phalange bone
Hand_Ring2       = Hand_Start + 13 // ring intermediate phalange bone
Hand_Ring3       = Hand_Start + 14 // ring distal phalange bone
Hand_Pinky0      = Hand_Start + 15 // pinky metacarpal bone
Hand_Pinky1      = Hand_Start + 16 // pinky proximal phalange bone
Hand_Pinky2      = Hand_Start + 17 // pinky intermediate phalange bone
Hand_Pinky3      = Hand_Start + 18 // pinky distal phalange bone
Hand_MaxSkinnable= Hand_Start + 19
// Bone tips are position only. They are not used for skinning but are useful for hit-testing.
// NOTE: Hand_ThumbTip == Hand_MaxSkinnable since the extended tips need to be contiguous
Hand_ThumbTip    = Hand_Start + Hand_MaxSkinnable + 0 // tip of the thumb
Hand_IndexTip    = Hand_Start + Hand_MaxSkinnable + 1 // tip of the index finger
Hand_MiddleTip   = Hand_Start + Hand_MaxSkinnable + 2 // tip of the middle finger
Hand_RingTip     = Hand_Start + Hand_MaxSkinnable + 3 // tip of the ring finger
Hand_PinkyTip    = Hand_Start + Hand_MaxSkinnable + 4 // tip of the pinky
Hand_End         = Hand_Start + Hand_MaxSkinnable + 5
Max              = Hand_End + 0

現在の骨格IDを取得する

OVRSkeleton.csは、現在の骨組みの開始骨格ID、終了骨格ID、骨格総数を取得するための手段を提供します。

  • 開始および終了の骨格IDを取得するには、GetCurrentStartBoneID()およびGetCurrentEndBoneId()のメソッドを呼び出します。これらは主に、現在構成されている骨組みタイプの中に存在する骨格IDサブセットに関する反復処理に使用されます。
  • GetCurrentNumBones()およびGetCurrentNumSkinnableBones()のメソッドを呼び出し、骨組み内の骨格総数およびスキン設定可能な骨格総数を取得します。BonesとSkinnableBonesの間の違いは、Bonesの場合は指先のアンカーも含まれているという点です。ただし、それらはメッシュとアニメーションの点では手の骨組みの一部ではありません。一方、スキン設定可能な骨格にはフィルター処理される先端があります。

インタラクションを追加する

さまざまなアプリ間でインタラクションを標準化するため、ハンドトラッキングAPIではフィルター処理されたポインターポーズとピンチジェスチャーの検出が公開されています。ポイントとクリックのインタラクションのみを必要とするシンプルなアプリでは、ポインターポーズを使用して、手をシンプルなポインティングデバイスとして扱うことができます。ピンチジェスチャーがクリックアクションとみなされます。

OVRHand.csはポインターポーズとピンチ操作へのアクセスを提供します。それにより、アプリをOculusシステムアプリと同じインタラクションモデルに確実に準拠させることができます。以下のセクションでは、手に実行できるいくつか機能について説明します。

手と信頼性レベルをトラッキングする

どの時点でも、アプリのロジックで、アプリが手を検出したかどうかをチェックすることができます。OVRHand.csは、現在手が見えているか、それとも隠れていてデバイスでトラッキングできないかを検証するIsTrackedプロパティを提供しています。また、トラッキングシステムの全体的な手のポーズについての信頼性レベルを示すHandConfidenceプロパティも提供しています。このプロパティは、信頼性レベルをLowHighHandConfidence値として返します。

アプリのロジックでHandConfidence値を使用することにより、手のレンダリングをコントロールすることができます。例えば、信頼性が低い場合には手をレンダリングしないようにします。IsTrackedtrueで、HandConfidenceHighである場合のみ、レンダリングとインタラクションにハンドポーズデータを使用するようおすすめします。

ハンドスケールを取得する

ユーザーの手のスケールは、デフォルトのハンドモデルスケールを1.0とした相対値として取得します。

  • HandScaleプロパティを呼び出すと、リファレンスハンドサイズを基準とした現在のユーザーの手のスケールを示す浮動小数点値が返されます。

例えば、値が1.05の場合、それはユーザーの手のサイズがリファレンスハンドより5%大きいことを示しています。値は随時変更されるため、アプリはこの値を使用して、実行時のレンダリングとインタラクションシミュレーションのために手のスケールを調整します。

ピンチ操作を統合する

ピンチ操作は、手を使用するUIインタラクションとしては、昔からある基本的なインタラクションです。人差し指のピンチ操作が適切に行われると、コントローラーの通常の選択やトリガーのアクションと同じ操作、つまり、UI上のボタンなどのコントロールをアクティブにする操作とみなされます。

指が現在ピンチ操作をしているかどうかを検出し、そのピンチ操作の強さをチェックするには、OVRHand.csからGetFingerIsPinching()およびGetFingerPinchStrength()のメソッドを呼び出します。クエリの対象となる指について、HandFinger列挙で定義される、関係する指の定数を渡します。指の定数は、ThumbIndexMiddleRing、およびPinkyです。

使用例

var hand = GetComponent<OVRHand>();
bool isIndexFingerPinching = hand.GetFingerIsPinching(HandFinger.Index);
float ringFingerPinchStrength = hand.GetFingerPinchStrength(HandFinger.Ring);

ピンチジェスチャーの連続は、返される浮動小数点値によって示されます。指ピンチ操作ごとに、対応する値の範囲は0(ピンチ操作なし)~1(指が親指に接触する完全なピンチ操作)です。

ピンチ操作の強度に加えて、OVRHand.csには、指ポーズの信頼性レベルを測定するGetFingerConfidence()メソッドもあります。低いか高いかが測定され、指のポーズに関するトラッキングシステムの信頼性の程度を示すものです。

  • 指ポーズの信頼性レベルを取得するには、GetFingerConfidence()メソッドを呼び出し、信頼性レベルをトラッキングしたい指の定数を渡します。

使用例

var hand = GetComponent<OVRHand>();
TrackingConfidence confidence = hand.GetFingerConfidence(HandFinger.Index);

ポインターポーズを統合する

トラッキングされている手から安定したポインティング方向を導出することは、フィルタリング、ジェスチャー検出、およびその他の要因が関係する重要なタスクです。OVRHand.csには、アプリ間でポインティングインタラクションの一貫性を維持するためのポインターポーズがあります。これは、トラッキングスペース内のポインティングレイの開始点と位置を示します。UIインタラクションの場合、PointerPoseを使用し、ユーザーが指している方向を判断することをおすすめします。

  • OVRHand.csからPointerPoseプロパティを呼び出します。

ポインターポーズは、ユーザーの手の位置、トラッキングステータス、その他の要因により、有効な場合とそうでない場合があります。IsPointerPoseValidプロパティを呼び出すと、ポインターポーズが有効かどうかを示すブーリアンが返されます。ポインターポーズが有効な場合、レイをUIのヒットテストに使用できます。有効でない場合、レイのレンダリングに使用しないでください。

システムジェスチャーを確認する

システムジェスチャーは予約済みジェスチャーであり、ユーザーはOculusユニバーサルメニューに移動できます。この操作は、ユーザーが、利き手の手のひらを開いた状態でヘッドセットの上方向に手を上げた後、人差し指でピンチ操作をして行います。利き手でない方の手を使ってこのジェスチャーを実行しようとすると、Button.Startイベントがトリガーされます。Button.Startをポーリングして、ボタンを押すイベントのアクションをアプリロジックに統合できます。

利き手を検出するには、OVRHand.csからIsDominantHandプロパティを呼び出します。ユーザーがシステムジェスチャーを実行しているかどうかをチェックするにはOVRHand.csからIsSystemGestureInProgressプロパティを呼び出します。IsSystemGestureInProgressプロパティがtrueを返す場合に、システムジェスチャーが進行中であることをユーザーに示す視覚フィードバック(手のマテリアルを別の色を使ってレンダリングしたりハイライトしたりするなど)をアプリで提供するようおすすめします。また、ユーザーがシステムジェスチャーを実行している間、アプリはカスタムジェスチャー処理を一時停止しなければなりません。これにより、ユーザーがOculusユニバーサルメニューに移動しようとしている際に、アプリがジェスチャーベースのイベントをトリガーすることを回避できます。

トラブルシューティング

以下の質問は、アプリでの手のレンダリングや統合を行う際に発生する問題のトラブルシューティングに役立ちます。

  • アプリで手が表示されないのはなぜですか?

    アプリで手がレンダリングされない理由として、さまざまな原因が考えられます。まず、デバイスでハンドトラッキングが有効になっていること、またシステムメニューで手が適切に動作していることを確認します。アプリのAndroidManifest.xmlファイルで設定されているアクセス許可を確認します。OVRHandPrefab prefabを使用してシーンに手を追加してあることを確認します。

  • 手がぼけている、または薄く見えるのはなぜですか?

    Oculus Quest上のカメラの視野が限られているために手が正しくトラッキングされていない可能性があります。適切にトラッキングされるよう、手をOculus Questの正面に近づけてください。

  • ピンチ操作のジェスチャーに人差し指以外の指を使うことはできますか?

    はい。OVRHand.csからOVRHand.GetFingerIsPinching()メソッドを使用し、トラッキングする指を指定します。指のトラッキングについて詳しくは、「ピンチ操作の統合」をご覧ください。

ハンドトラッキングの制限事項について

Oculus Questのハンドトラッキングは現在のところ実験的機能であり、いくつかの制限事項があります。これらの制限事項は、将来緩和または廃止される可能性がありますが、現時点では予期される動作の一部です。具体的な点については、「トラブルシューティング」のセクションをご覧ください。

オクルージョン

一方の手がもう一方の手に遮られると、トラッキングが失われたり、手の信頼性が低下したりすることがあります。大抵、アプリは手をフェードアウトすることでこれに対応します。

ノイズ

ハンドトラッキングではノイズが発生することがあります。これは、ライティング条件や環境条件に影響されることがあります。ジェスチャー検出のアルゴリズムを開発する際には、それらの条件を考慮してください。

コントローラーと手

現在、コントローラーと手は同時にトラッキングされません。アプリでは、手とコントローラーの両方ではなく、どちらか一方をサポートするようにします。

ライティング

ライティングに関して、ハンドトラッキングには、インサイドアウト(ヘッド)トラッキングとは異なる要件があります。状況によっては、これによりヘッドトラッキングとハンドトラッキングの間で機能的な違いが生じることがあり、片方が機能している間もう一方が機能を停止する可能性があります。