ハンド トラッキング — MRTK3
概要
多関節ハンド ジョイント データは、まだ Unity Input System でネイティブに処理されない数少ない入力データの 1 つであり、サブシステムで処理されます。
注意
MRTK3 サブシステムおよびそれらと MRTK 2.x サービスの違いをよく理解していない場合は、MRTK3 サブシステムのアーキテクチャに関するドキュメントを参照して、当社の理念と設計を詳しく確認してください。
サブシステムでは、複数のソースからハンド ジョイント データを取り込み、それらをデバイスやシミュレーション コンテキスト間で動作する中央 API に集約します。 以下のサブシステムは、HandsSubsystem
の実装です。
OpenXRHandsSubsystem
は OpenXR プラグインから直接ハンド データを受け取ります。XRSDKHandsSubsystem
は Unity の XR SDK 抽象化レイヤーからハンド データを受け取ります (このレイヤーは OpenXR またはその他のソースからデータを調達している可能性があります)。SyntheticHandsSubsystem
は、システムからの入力アクション (devicePosition
やdeviceRotation
など) に基づいて偽のハンド ジョイントを合成します。 このサブシステムでは、エディター内で入力シミュレーションを使用するときに表示されるジョイントを提供します。
HandsAggregatorSubsystem
は、ハンド データのすべてのソースを中央 API に結合するサブシステムです。 これは、アクティブに実行されているすべてのから骨格関節データを引き出します HandsSubsystems
. の MRTK 実装 HandsAggregatorSubsystem
は であり、 MRTKHandsAggregatorSubsystem
フレームごとのハンド データの遅延読み込みと再利用をサポートします。
重要
ハンド ジョイント データに対して直接クエリを実行する場合は、個々のハンド サブシステムからではなく、必ずアグリゲーターからクエリを実行してください。 これにより、シミュレートされたデータを含むあらゆるハンド データのソースに対してコードが機能します。
アグリゲーターとハンド サブシステムでは、後から着信ハンド データ要求を評価します。 ハンド データのクエリは、"クライアント" スクリプトから要求されるまで実行されません。 アプリから個々のジョイントのみが要求される場合、ハンド サブシステムは評価を遅延して、基になる API から 1 つのジョイントに対してのみクエリを実行します。 さらに、"クライアント" からハンド全体に相当するジョイント データが要求された場合、同じフレーム内の後続の呼び出しで同じデータが再利用されるため、同じフレーム内の多くのジョイントに対してクエリを実行するコストが削減されます。 新しいフレームごとに、使用されたキャッシュがフラッシュされ、その後の呼び出しによってキャッシュの再補充が開始されます。
その結果、アプリケーションをプロファイリングするときに、フレーム内の最初のジョイントのクエリに、後続のクエリよりも時間がかかる場合があります。 これは、最初のクエリに関連する償却コストと、後続の "キャッシュ ヒット" の相対的なパフォーマンスによるものです。
ピンチの特性
アグリゲーターは、特定のハンド サブシステムのそれぞれからクエリを実行するジョイント データに基づいて、ピンチ ジェスチャーに関するいくつかの測定値を計算します。 これらの測定値は、アグリゲーター サブシステム構成で構成されます。
ピンチ オープンしきい値とピンチ クローズしきい値では、ピンチの進行状況の正規化に使用される親指と人差し指の間の絶対世界距離を制御します。 距離がクローズしきい値と等しい場合、ピンチの進行状況は 1.0 になり、距離がオープンしきい値と等しい場合は 0.0 になります。 (これらのしきい値は現在は世界単位ですが、間もなくユーザーの手のサイズに正規化されます。)
ハンド レイズ カメラ FOV では、ユーザーのビューの中心からどれくらいの位置で、手をピンチに対して有効と見なすかを制御します。 ハンド フェイシング アウェイ許容値では、ユーザーの手の回転を測定する際の許容値を制御して、ユーザーが掌を向けていることを判別します。
ハンズ アグリゲーターの例
// Get a reference to the aggregator.
var aggregator = XRSubsystemHelpers.GetFirstRunningSubsystem<HandsAggregatorSubsystem>();
// Wait until an aggregator is available.
IEnumerator EnableWhenSubsystemAvailable()
{
yield return new WaitUntil(() => XRSubsystemHelpers.GetFirstRunningSubsystem<HandsAggregatorSubsystem>() != null);
GoAhead();
}
// Get a single joint (Index tip, on left hand, for example)
bool jointIsValid = aggregator.TryGetJoint(TrackedHandJoint.IndexTip, XRNode.LeftHand, out HandJointPose jointPose);
// Get an entire hand's worth of joints from the left hand.
bool allJointsAreValid = aggregator.TryGetEntireHand(XRNode.LeftHand, out IReadOnlyList<HandJointPose> joints)
// Check whether the user's left hand is facing away (commonly used to check "aim" intent)
// This is adjustable with the HandFacingAwayTolerance option in the Aggregator configuration.
// "handIsValid" represents whether there was valid hand data in the first place!
bool handIsValid = aggregator.TryGetPalmFacingAway(XRNode.LeftHand, out bool isLeftPalmFacingAway)
// Query pinch characteristics from the left hand.
// pinchAmount is [0,1], normalized to the open/closed thresholds specified in the Aggregator configuration.
// "isReadyToPinch" is adjusted with the HandRaiseCameraFOV and HandFacingAwayTolerance settings in the configuration.
bool handIsValid = aggregator.TryGetPinchProgress(XRNode.LeftHand, out bool isReadyToPinch, out bool isPinching, out float pinchAmount)
ハンド コントローラー プレハブ
MRTK LeftHand Controller
と MRTK RightHand Controller
プレハブを使用すると、プロジェクトでハンド コントローラーを使用できます。 これらのプレハブは、多関節ハンドコントローラーと非関節ハンドコントローラーの両方で動作します。 彼らは、突っ込み、グラブ、遠距離、視線入力のピンチアクションのための対話機能を持っています。 また、これらのプレハブは適切なビジュアルを示し、コントローラーとインタラクター コンポーネントを使用してデバイスからの入力アクションを処理します。 これらのコンポーネントは、入力バインディングを宣言する Unity の入力アクション マッピングを使用します。 既定では、プレハブは、含まれている MRTK Default Input Actions
資産で定義されている入力アクション マッピングを使用します。
ハンド コントローラー プレハブはプレハブに既に MRTK XR Rig
含まれています。詳細については、「 新しいシーンの作成 」を参照してください。 MRTK3 の XR リグが既に使用されている場合は、ハンド コントローラーをサポートするためにそれ以上のアクションは必要ありません。
重要
MRTK3 の XR リグの入力アクションが変更され、アセットの外部で定義されたアクションを MRTK Default Input Actions
使用するようにする場合は、新しい入力アクション アセットを指すよう MRT3 の入力アクション マネージャーを更新してください。 これを行わないと、未定義の動作が発生する可能性があります。
MRTK3 の左右のコントローラー プレハブには、手入力をサポートするために必要なすべてのコンポーネントが含まれています。 そのようなコンポーネントの 1 つは MRTK の ArticulatedHandController
です。これは、Unity XR 入力 ActionBasedController
の 特殊なバージョンです。 この MRTK3 コントローラー スクリプトでは、さまざまなハンド入力イベントを公開するために、MRTK3 のハンド アグリゲーター サブシステムを使用します。 たとえば、コントローラーはピンチ選択イベントを公開します。
ハンド プレハブには、ハンド コントローラーの視覚化を可能にするスクリプトもあります。 コンポーネントは HandJointVisualizer
デバッグ用であり、各ハンド ジョイントにインスタンス化されたメッシュを描画します。 ControllerVisualizer
コンポーネントは運用環境のシナリオを対象としていますが、コントローラーが検出されると、対応するコントローラー モデルがレンダリングされます。 プラットフォームのコントローラー メッシュは、使用可能な場合は使用されます。それ以外の場合は、フィールドで fallbackControllerModel
指定された汎用コントローラー モデルが使用されます。
HoloLens 以外のプラットフォームでは、 を RiggedHandMeshVisualizer
使用して手を視覚化できます。 名前で示されているように、このビジュアライザーはリギングされたメッシュを使用して高品質のハンド モデルをレンダリングします。HoloLens などの AR プラットフォームでは、パフォーマンスと設計上の理由から推奨されません。 このビジュアライザーは、既定のハンド コントローラー プレハブでは構成されていないことに注意してください。
Note
HoloLens などの拡張現実プラットフォームでは、手の視覚エフェクトを使用しないことをお勧めします。 ユーザーの実際の手と少し遅れたホログラフィック視覚化の間の競合は、価値よりも気が散る可能性があります。 ただし、不透明なプラットフォームの場合、これは優れたソリューションです。
既定のハンド コントローラー プレハブでは、一連の対話コンポーネントもホストされます。 これには、PokeInteractor
、MRTKRayInteractor
、GrabInteractor
、および GrabInteractor
が含まれます。 これらの対話機能の詳細については、「 Interactor Architecture — MRTK3」を参照してください。
最後に、コントローラー プレハブには、検出器コンポーネント、、IInteractionModeDetector
NearInteractionModeDetector
および InteractionDetector
も含まれます。 これらのコンポーネントは、どのインタラクターを有効にすべきかをアプリケーションの対話モード マネージャーに通知します。 MRTK3 のディテクタの詳細については、「 相互作用モード マネージャー - MRTK3」を参照してください。
ポーズ ソース
MRTK3 のすべてのハンド インタラクターには、コントローラーのポーズ (または手のポーズ) が必要です。 手のポーズの種類は、対話機能によって異なる場合があります。 たとえば、Unity の入力アクションを使用して位置と回転を取得するものもあれば、人差し指ポーズを使用するものもあれば、手のひらの姿勢を使用するものもあります。 各インタラクターのハンド ポーズ ソースは、MRTK3 IPoseSource
のインターフェイスを実装するクラスによって定義されます。 このインターフェイスでは、次の宣言が行われます。
TryGetPose
. このメソッドは、ワールド空間で手のポーズを取得しようとします。 たとえば、返される姿勢は、MRTK3 のハンド アグリゲーター サブシステムから取得された手関節姿勢に対応している場合があります。 ポーズの取得が成功した場合、このメソッドは return を返します。 このメソッドの一部の実装 (手の関節データからポーズを取得するなど) は、データが使用できない場合に失敗する可能性があります。
対話機能の IPoseSource
型は Unity インスペクターを使用して指定され、次のいずれかの型にすることができます。
FallbackCompositePoseSource
. ポーズ ソースの順序付きリストから計算されたポーズ ソース。 ポーズを正常に返す最初のポーズ ソースの結果を返します。HandBasedPoseSource
. MRTK3 のハンド アグリゲーター サブシステムへのアクセス権を持つ特定の利き手に基づくポーズ ソースを定義するのに役立つ抽象クラス。HandJointPoseSource
. 特定の手の関節を拡張HandBasedPoseSource
して追跡するポーズ付きソース。InputActionPoseSource
. 指定した Unity 入力アクションから追跡された位置と回転で構成されるポーズを取得するポーズ ソース。 既定の入力アクションは、Unity アセットにありますMRTK Default Input Actions
。PinchPoseSource
. MRTK3 のハンド アグリゲーター サブシステムから特定のハンドのピンチ ポーズを拡張HandBasedPoseSource
して取得するポーズ ソース。PolyfillHandRayPoseSource
. ハンド レイを拡張HandBasedPoseSource
して表すポーズ ソース。 このハンド レイは、MRTK3 のハンド アグリゲーター サブシステムから手のひらとナックルの位置から派生することによって構築されます。
手の対話機能のポーズ ソースの種類は、MRTK3 の既定のコントローラー プレハブで既に指定されています。 プレハブの既定のポーズ ソース設定を変更することはお勧めしません。