SteamVR Skeletal Hand Tracking ドライバーガイド
このガイドは、VRChatが SteamVR Input 2.0 にアップデートされることに伴い、カスタム SteamVR Skeletal Input Drivers の開発者がドライバーをVRChatで正しく動作させるための手助けを目的としています。既存のドライバーが正しく動作することを確認したい場合や、SteamVR経由でVRChatで使用する新しいドライバーをゼロから作成する場合、Valveによる SteamVR Skeletal Driver 作成に関するドキュメント および、より広範な Driver API Documentation を併せて確認することをお勧めします。
VRChatはいつ、どのようにしてSteamVRのスケルトンデータを使用するか?
アバターのアニメーション
アバターの手をアニメーションさせる目的で、VRChatは SkeletonLeftHand または SkeletonRightHand アクションが入力ソースにバインドされており、利用可能な状態であれば常にそのスケルトンデータを使用します。いずれの場合も、 VRSkeletalMotionRange_WithoutController のスケルトンアニメーションがアクションから取得され、中間データとして保存されます。この中間データの内部表現には、ボーンの 位置 と 回転 の両方が格納されますが、本ドキュメントの執筆時点では、アバターに適用されるリターゲティングは 回転 のみを提供します。これは、アバターの3Dハンドメッシュが、指の長さが異なる多様な手に対して関節位置がうまく機能するように慎重に設計されていない限り、歪んだり潰れたりして見える可能性があるためです。この欠点は、比率の異なるアバターの手では、ピンチやグラブといったアクションの視覚的フィードバックとして正確に機能することが保証できないという点にあります。
ゲームプレイ、メニュー等の入力としての使用
VRChatは、スケルトンアクションの eSkeletalTrackingLevel 値が VRSkeletalTrackingLevel.VRSkeletalTracking_Full である場合に限り、提供されたスケルトンアニメーションデータの手ごとの入力として使用することを決定します。
念のため、 eSkeletalTrackingLevel には以下の値があります。
VRSkeletalTracking_Estimated- デバイス側で身体部位の位置を直接特定できません。デバイスから提供されるスケルトンポーズは、ボタン、トリガー、ジョイスティック、その他の入力センサーをアクティブにするために必要な位置を想定して推定されたものです。Viveコントローラーが最もよく知られた例です。VRSkeletalTracking_Partial- 身体部位の位置を直接測定できますが、実際の身体部位よりも自由度が低くなります。特定の身体部位の位置がデバイスによって測定されず、他の入力データから推定される場合があります。例:Indexコントローラー、Eteeコントローラー、指の曲げのみを測定するグローブなど。VRSkeletalTracking_Full- 身体部位の位置を、その身体部位の可動域全体にわたって直接測定できます。例:Ultraleapトラッキング、Metaハンドトラッキング、MediaPipeハンドトラッキング、各指の節の回転を測定するグローブなど。
したがって、VRChatがなぜこの値を使用するのかは明らかでしょう。それは、供給されたスケルトンの中に、手のポーズに関する 実際の情報 がどれだけ含まれているかを直接示しているからです。APIの中でこの種の情報を提示しているのはここだけであり、この目的のために使用する必要があります。
フルフィデリティ(完全忠実度)なスケルトンハンドトラッキングのインタラクションモデルは、私たちがスケルトンデータに対して非常に複雑な処理を行うことによって構築されています。私たちは、親指の先から他の指の先までの距離をチェックすることで独自の pinch detection(ピンチ検出)を計算し、UIでの「クリック」や、すべての指(人差し指、中指、薬指、小指)の親指と指先のピンチに基づくジェスチャー入力に使用しています。現在のジェスチャーアクションは以下の通りです。
左手:
- 親指と人差し指のピンチ:
- 手のひらがユーザーの顔に直接向いている時:メニューを開く
- 手のひらが外側を向いており、レイキャストがアクティブな時:UIクリック
- 親指と中指のピンチ:移動
- 親指と薬指のピンチ&ホールド(ユーザーの顔の方を向いている時):マイクミュート
- 親指と小指のピンチ&ホールド(ユーザーの顔の方を向いている時):ジェスチャー入力を無効化
右手:
- 親指と人差し指のピンチ:なし
- 親指と中指のピンチ:回転
- 親指と薬指のピンチ(ユーザーの顔の方を向いている時):ジャンプ
- 親指と小指のピンチ(ユーザーの顔の方を向いている時):キャンセル/ドロップ
つまり、スケルトンハンドトラッキングの元となっている「デバイス」に関連する、スケルトンやポーズ以外の(ブール値、スカラー、Vector2等の) input component handles から、これらのアクションを提供する必要はありません。実際、それを行うとダブルクリックや意図しない操作が発生する可能性があります。これについては後ほど Controller Emulation セクションで詳しく説明します。
また、これは 関節のポーズを正しく計算することが極めて重要である ということも意味します。ほとんどのトラッキングシステムでは、SteamVRの座標系に合わせるために何らかの座標変換が必要となり、このプロセスでエラーが発生する可能性があります。次のセクションでは、スケルトンデータを視覚的に確認する方法について説明します。
スケルトンデータの視覚的なデバッグ
デバッグ目的でスケルトンデータを視覚化することができます。

これらはメニュー内で accurate hands(正確な手)と呼ばれています。これらは常にメニューや読み込みシーン、あるいはアバターがジェネリック(非ヒューマノイド)アバターの場合に表示されます。また、コントロールメニューから、ローカル(ネットワーク越しには見えない)でアバターの手をこれに 置き換える ように設定することも可能です。
上のキャプションで示されている通り、VRChatには、(Avatar Handsとは対照的な) Accurate Hands と呼ぶハンドビジュアライゼーション機能があります。これは、3Dハンドメッシュとしての見た目を維持しつつ、基礎となるトラッキングデータを可能な限り忠実に表現したものです。多くの場面で役立ちますが、本ドキュメントでは、提供されるトラッキングデータが正確であり、最高の入力エクスペリエンスを提供できるように調整されているかを確認するためのデバッグ・確認ツールとして使用することを推奨します。ピンチジェスチャーを行う際には指先が触れている必要があり、使用しているトラッキングシステムが各関節の長さを測定するものであれば、それも同様に反映されているはずです。
このモードを有効にするには、Main Menu を開き、Settings ページに移動してから、Controls カテゴリを選択してください。

右側の「Accurate」ボタンをクリックしてください。これで手が切り替わります。
Controller Emulation
現在、SteamVRで光学式フィンガートラッキング(あるいはグローブ型デバイス)を動作させるために最も一般的に行われている手法は、「コントローラーエミュレーション」と呼ばれるアプローチです。これは、カスタムのSteamVRドライバーが、既存のSteamVRエコシステムで広く知られているデバイス(通常はTouchやIndexコントローラー)のinput profile、properties、およびrendermodelを流用し、そのデバイスになりすますというものです。その上で、ソースとなるトラッキングシステム(Meta QuestやUltraleapなど)からのスケルトンデータをスケルトン・トラッキング入力ハンドル経由で送信し、アプリケーションのスケルトン・トラッキングアクションへと送ります。この際、fidelity levelをfullとして送信することもあります。この手法によりアプリケーションへフィンガートラッキングのデータを渡すことは可能ですが、理想的なアプローチではありません。
- アプリケーション側は、実際に使用されているハードウェアが何であるかを識別できません。
- コントローラーのプロパティの一部(fidelity level enumなど)は、スケルトン入力コンポーネントが初期化された後に変更できません。そのため、実行時にコントローラーとハンドトラッキングを切り替えるようなマルチモーダルな操作に対して、アプリケーション側が応答することは不可能です。
- バーチャルコントローラーのその他の入力(トリガー、ジョイスティック、ボタンなど)を埋めるための最も簡単な方法は、単純で見えないジェスチャーを割り当てることですが、これはユーザー体験の観点から見てフラストレーションの原因となります。
- その他のアクション(前述のトリガー、ジョイスティック、ボタンなど)に対するバーチャル入力は、トラッキングデータから生成されたアプリケーション側の入力と競合する可能性があります。これは、メニュー操作時にダブルクリックが発生したり、ドライバーとアプリケーションのジェスチャー入力システムの両方で同時にグラブイベントがトリガーされたりといった形で現れることがあります。これらはユーザーにとって予期せぬ混乱を招く結果となります。
- ユーザーは、フィンガートラッキング用とコントローラー保持用で別々のバインディングを設定することができません。前述の問題を回避するためにハンドトラッキング用の入力アクションマッピングを変更または無効化した場合、その設定はコントローラーに戻した際にも適用されたままになります。クリックやグラブの操作において、コントローラーに戻った際にそれらの操作ができなくなってしまう可能性があります。
こうした理由から、私たちは「コントローラーエミュレーション」というアプローチを公式にはサポートしていません。VRChatにはこの状態を検知するためのコードが含まれており、入力がサポートされていない旨をユーザーに通知する場合や、意図しない副作用が生じる可能性があります。
Please SteamVRやVRChatに対して送信するハードウェアや入力情報を偽らないでください。Valveのドキュメントにおいて、VRChatがフィンガートラッキングを有効にする前に現在のコントローラーがKnucklesであるかを確認していることや、VRChatをターゲットとする場合にはValve組み込みの汎用コントローラーエミュレーションを使用すべきであるといった記述が見受けられるかもしれません。これは現在では誤りです。 本ガイドが最新かつ正式な情報となります。VRChat向けにこのエミュレーションシステムを使用したコントローラーエミュレーションのバインディングを既に設定している場合は、削除してください。
推奨されるアプローチ
ストリーミングアプリケーション
Meta QuestのようなスタンドアロンデバイスをSteamVRに接続するストリーミングアプリケーションを構築する場合、そのアプリケーションは、コントローラーを使用しないハンドトラッキングに加えて、Touchのようなトラッキングコントローラーをサポートすることが望ましいでしょう。また、片方の手でコントローラーを持ち、もう片方の手はコントローラーを使わずにトラッキングされる「マルチモーダル」な利用法に加え、コントローラーから手へ素早く切り替えられるようにサポートしたい場合もあるでしょう。lighthouseのような既存のSteamVRドライバーが示すように、1つのSteamVRドライバー内に複数の入力デバイスを共存させることができます。したがって、推奨されるアプローチは以下の通りです。 ストリーミングアプリケーションがサポートする既存の物理コントローラーの種類ごとに、仮想コントローラー(input profile、tracked device idおよびproperties、input component handlesなど)を作成します。 コントローラーを使用しないハンドトラッキング専用の、全く新しい仮想コントローラーを作成します。
物理コントローラー
これらについては、パススルーするコントローラーを複製するだけで十分です。これらは、通常備えているものと同じ入力プロファイルとコンポーネント(サムスティック、ボタンなど)、同じトラッキングデバイスプロパティ(モデル名、レンダリングモデル、メーカーなど)、同じ入力ソース/ロール(コントローラーの場合は左右の手、HMDの場合は頭)を持つべきであり、スケルトントラッキングレベルをコントローラーが提供するもの(Touchの場合はEstimated)に初期化します。
ハンドバーチャルコントローラー
これらについては、必要最小限の入力機能を提供する入力プロファイルとコンポーネントハンドルが必要となります。これらは以下の通りです。
- Dashboard
- System click(ダッシュボードとのインタラクション用)
- Hand Pose
- Skeleton
必要であれば他の入力機能を提供することもできます(特にジェスチャーがうまく設計されている場合や、それに対するフィードバックを提供するオーバーレイがある場合は推奨されます)。ただし、VRChatに提供するデフォルトのバインディングには含めないことを推奨します。 ここからは、仮想ハンドコントローラー用の説明的なプロパティセットを提供する必要があります。仮の例として、ストリーミングアプリが「Bitriver」で、Meta Questからスケルトンハンドトラッキングをストリーミングする場合を考えます。各プロパティに対して以下のように設定できます。
左右の手共通:
| Property | Value |
|---|---|
| Prop_ManufacturerName_String | Meta |
| Prop_TrackingSystemName_String | Oculus Insight |
| Prop_ModelNumber_String | Bitriver_Hand |
| Prop_ControllerType_String | Bitriver_Hand |
| TrackedDeviceClass | Controller |
| Prop_InputProfilePath_String | Path to input profile json file |
左手用:
| Property | Value |
|---|---|
| Prop_SerialNumber_String | BitRiver_Left_Hand |
| Prop_ControllerRoleHint_Int32 | 1 |
右手用:
| Property | Value |
|---|---|
| Prop_SerialNumber_String | BitRiver_Right_Hand |
| Prop_ControllerRoleHint_Int32 | 2 |
Skeletal Inputをサポートするすべてのコントローラーはトラッキングデバイスを持ち、このトラッキングデバイスのPoseコンポーネントはスケルトンのBase Poseと呼ばれます。スケルトンの変換座標空間は、このBase Poseの子となります。
ユーザーのVRシステムがハンドトラッキングとコントローラートラッキングの切り替えを示したとき、vr::VRserverDriverHost()-> TrackedDevicePoseUpdated() を呼び出す際に、各トラッキングデバイスのBase Poseコンポーネント内で送信するブール値を変更して、この切り替えを示す必要があります。DriverPose_t内の関連フィールドは以下の通りです。
poseIsValiddeviceIsConnected
コントローラーがアクティブなときは、それらの poseIsValid を true に(使用しているAPIがポーズの信頼性が低く拒否すべきであると示す場合などを除き)、また deviceIsConnected を true に設定します。次に、仮想ハンドの poseIsValid を false に、仮想ハンドの deviceIsConnected を false に設定します。
ハンドトラッキングがアクティブなときは、逆の値を設定します。コントローラーのトラッキングデバイスポーズコンポーネントの poseIsValid と deviceIsConnected を false に設定し、仮想ハンドの poseIsValid は手がトラッキングされているときは true に、トラッキングされていないときは false に設定し、deviceIsConnected を true に設定します。
PCVR周辺機器
PCVR向けの単一の周辺機器を構築する場合(独自のコンピュータビジョンによるハンドトラッキングシステムの作成や、グローブの製作など)、前述のセクションの後半部分、つまり手を表現するために適切に命名された新しいバーチャルコントローラーを構築する作業のみを行う必要があります。コントローラーと手のハンドオフ(切り替え)を行う必要はありません。
Finger Tracking Exclusive Mode(フィンガートラッキング排他モード)
VRChatでは将来的にこの機能を削除する可能性があります。各種アクションに対して独自の入力を提供する非準拠のドライバーを使用すると、ユーザー体験が低下する恐れがあります。
この機能は、VRChatの開発中に使用されていたものです。当時はすべてのドライバーが、VRChat独自のトラッキングベースの入力システムが自前で推論可能なSteamVRアクションに対して入力を提供していました。Finger Tracking Exclusive Modeは、開発中にダブルクリックやダブルグラブといった不具合を起こさず、フル精度のハンドトラッキングを実現するために使用されました。
ユーザーがFinger Tracking Exclusiveモードを有効にすると、VRChatは Pose、SkeletonLeftHand、および SkeletonRightHand 以外のすべてのアクションにバインドされたSteamVR入力を無視するようになります。
最終更新: