Unity でのジェスチャ

HoloLens とイマーシブ HMD で Unity の視線入力を操作するには、手のジェスチャモーション コントローラーの 2 つの主要な方法があります。 Unity の同じ API を使用して、空間入力の両方のソースのデータにアクセスします。

Unity では、Windows Mixed Reality の空間入力データにアクセスする主な方法を 2 つ提供しています。 共通の Input.GetButton/Input.GetAxis API は、複数の Unity XR SDK で機能するのに対し、Windows Mixed Reality に固有の InteractionManager/GestureRecognizer API では、空間入力データの完全なセットが公開されます。

高レベル複合ジェスチャ API (GestureRecognizer)

名前空間: UnityEngine.XR.WSA.Input
種類: GestureRecognizerGestureSettingsInteractionSourceKind

お使いのアプリで、空間入力ソース、タップ、ホールド、操作、ナビゲーションの各ジェスチャの高レベルな複合ジェスチャも認識できます。 GestureRecognizer を使用すると、モーション コントローラーの両方でこれらの複合ジェスチャを認識できます。

GestureRecognizer の Gesture イベントごとに、入力用の SourceKind と、イベント時にターゲット ヘッド レイが提供されます。 一部のイベントでは、コンテキスト固有の追加情報が提供されます。

GestureRecognizer を使用してジェスチャをキャプチャするには、いくつかの手順を実行する必要があります。

  1. 新しい GestureRecognizer を作成する
  2. 監視するジェスチャを指定する
  3. これらのジェスチャのイベントをサブスクライブする
  4. ジェスチャのキャプチャを開始する

新しい GestureRecognizer を作成する

GestureRecognizer を使用するには、GestureRecognizer を作成しておく必要があります。

GestureRecognizer recognizer = new GestureRecognizer();

監視するジェスチャを指定する

SetRecognizableGestures() を使用して、関心のあるジェスチャを指定します。

recognizer.SetRecognizableGestures(GestureSettings.Tap | GestureSettings.Hold);

これらのジェスチャのイベントをサブスクライブする

関心のあるジェスチャのイベントをサブスクライブします。

void Start()
{
    recognizer.Tapped += GestureRecognizer_Tapped;
    recognizer.HoldStarted += GestureRecognizer_HoldStarted;
    recognizer.HoldCompleted += GestureRecognizer_HoldCompleted;
    recognizer.HoldCanceled += GestureRecognizer_HoldCanceled;
}

Note

GestureRecognizer のインスタンスでは、ナビゲーションと操作のジェスチャは相互に排他的です。

ジェスチャのキャプチャを開始する

既定では、GestureRecognizer は、StartCapturingGestures() が呼び出されるまで、入力を監視しません。 StopCapturingGestures() が処理されたフレームの前に入力が実行された場合、StopCapturingGestures() が呼び出された後にジェスチャ イベントが生成される可能性があります。 GestureRecognizer は、ジェスチャが実際に発生した前のフレームでオンまたはオフになっていたかどうかを記憶しているため、このフレームの視線入力のターゲット設定に基づいてジェスチャ監視を確実に開始および停止することができます。

recognizer.StartCapturingGestures();

ジェスチャのキャプチャを停止する

ジェスチャの認識を停止するには:

recognizer.StopCapturingGestures();

GestureRecognizer を削除する

GestureRecognizer オブジェクトを破棄する前に、忘れずにサブスクライブされたイベントのサブスクライブを解除してください。

void OnDestroy()
{
    recognizer.Tapped -= GestureRecognizer_Tapped;
    recognizer.HoldStarted -= GestureRecognizer_HoldStarted;
    recognizer.HoldCompleted -= GestureRecognizer_HoldCompleted;
    recognizer.HoldCanceled -= GestureRecognizer_HoldCanceled;
}

Unity でのモーション コントローラー モデルのレンダリング

モーション コントローラー モデルとテレポート
モーション コントローラー モデルとテレポート

ユーザーが保持している物理コントローラーと一致するモーション コントローラーをアプリでレンダリングし、さまざまなボタンが押されたときにはっきりと発音するには、Mixed Reality ツールキット内の MotionController プレハブを使用します。 このプレハブにより、実行時にシステムにインストールされているモーション コントローラー ドライバーから正しい glTF モデルが動的に読み込まれます。 これらのモデルを、エディターで手動でインポートするのではなく、動的に読み込むことが重要です。これにより、ユーザーが使用する可能性のある現在および将来のコントローラーに対して、物理的に正確な 3D モデルがアプリで表示されるようになります。

  1. 作業の開始の手順に従って、Mixed Reality ツールキットをダウンロードし、それを Unity プロジェクトに追加します。
  2. 作業の開始手順の一環としてカメラを MixedRealityCameraParent プレハブに置き換えたら、準備完了です。 このプレハブには、モーション コントローラー レンダリングが含まれています。 含まれていない場合は、[プロジェクト] ペインから Assets/HoloToolkit/Input/Prefabs/MotionControllers.prefab をシーンに追加します。 そのプレハブを、ユーザーがシーン内でテレポートするときにカメラを移動するために使用する親オブジェクトの子として追加して、コントローラーがユーザーについてくるようにする必要があります。 アプリにテレポートが含まれていない場合は、シーンのルートにプレハブを追加するだけです。

オブジェクトの投擲

仮想現実でオブジェクトを投げることは、見た目より難しい問題です。 ほとんどの物理ベースの対話式操作と同様に、ゲーム内で投擲が予期しない方法で動作すると、すぐにわかり、没入感が失われます。 Microsoft では、物理的に正しい投擲動作を表現する方法について時間をかけて深く考え、いくつかのガイドラインを考え出し、これらを共有したいと思います。これらのガイドラインは、プラットフォームの更新を通じて有効になります。

投擲を実装する推奨方法の例については、こちらをご覧ください。 このサンプルは、こちらの 4 つのガイドラインに従っています。

  • コントローラーの位置ではなく "速度" を使用します。 Windows の 11 月の更新プログラムで、"概算" の位置追跡状態での動作の変更が導入されました。 この状態のとき、コントローラーに関する速度情報は、多くの場合、位置よりも長く高精度が維持されるため、その高精度が信用できる限り、報告され続けます。

  • コントローラーの "角速度" を組み込みます。 このロジックはすべて、上記のリンクされたパッケージ内の GetThrownObjectVelAngVel 静的メソッドの throwing.cs ファイルに含まれています。

    1. 角速度が保存されているため、投げられたオブジェクトは、投擲の瞬間と同じ角速度を維持する必要があります: objectAngularVelocity = throwingControllerAngularVelocity;

    2. 投げられたオブジェクトの質量中心がグリップ姿勢の原点にない可能性があるため、ユーザーの参照フレーム内のコントローラーの速度とは、速度が異なる可能性があります。 この方法で発生したオブジェクトの速度の部分が、コントローラーの原点を中心として投げられたオブジェクトの質量中心の瞬間的な接線速度です。 この接線速度は、コントローラーの角速度と、コントローラーの原点と投げられたオブジェクトの質量中心との間の距離を表すベクトルとの外積です。

      Vector3 radialVec = thrownObjectCenterOfMass - throwingControllerPos;
      Vector3 tangentialVelocity = Vector3.Cross(throwingControllerAngularVelocity, radialVec);
      
    3. 投げられたオブジェクトの合計速度は、コントローラーの速度とこの接線速度の合計です: objectVelocity = throwingControllerVelocity + tangentialVelocity;

  • 速度を適用する "時間" に細心の注意を払ってください。 ボタンが押されると、そのイベントが Bluetooth を介してオペレーティング システムにバブル アップされるまで、最大 20 ミリ秒かかる場合があります。 つまり、コントローラーの状態が押された状態から押されていない状態への変化 (またはその逆) をポーリングすると、それで取得するコントローラーの姿勢情報は、実際にはこの状態の変化よりも進んでいます。 さらに、ポーリング API によって提示されるコントローラーの姿勢は、フレームが表示される時点での可能性のある姿勢を反映するように前方予測されます。これは、将来 20 ミリ秒を超える可能性があります。 これは、保持されているオブジェクトの "レンダリング" には適していますが、Microsoft ではユーザーが投擲をリリースした瞬間の軌道を計算するため、オブジェクトを "ターゲット" にするための時間の問題が複雑になります。 幸い、11 月の更新プログラムで、InteractionSourcePressedInteractionSourceReleased などの Unity イベントが送信されると、ボタンが押されたときまたは離したときの過去の姿勢データが状態に含まれるようになります。 投擲中に最も正確なコントローラー レンダリングとコントローラー ターゲットを取得するには、必要に応じて、ポーリングとイベントを正しく使用する必要があります。

    • 各フレームをレンダリングするコントローラーの場合、アプリでコントローラーの GameObject を、現在のフレームのフォトン時間の前方予測コントローラーの姿勢に配置する必要があります。 このデータは、XR.InputTracking.GetLocalPositionXR.WSA.Input.InteractionManager.GetCurrentReading などの Unity ポーリング API から取得します。
    • 押すまたは離すをターゲットとするコントローラーの場合、その押すまたは離すイベントのコントローラーの姿勢の履歴に基づいて、アプリでレイキャストおよび軌道を計算する必要があります。 このデータは、InteractionManager.InteractionSourcePressed などの Unity イベント API から取得します。
  • グリップ姿勢を使用します。 角速度と速度は、ポインター姿勢ではなく、グリップ姿勢を基準にして報告されます。

投擲は、今後の Windows Update で引き続き改善されます。ここでその詳細を確認できます。

MRTK のジェスチャとモーション コントローラー

入力マネージャーからジェスチャとモーション コントローラーにアクセスできます。

チュートリアルに従う

詳細なカスタマイズ例が記載されたステップバイステップのチュートリアルは、Mixed Reality Academy でご利用いただけます。

MR 入力 213 - モーション コントローラー
MR 入力 213 - モーション コントローラー

次の開発チェックポイント

ここで述べる MRTK の主要機能の説明は、Microsoft による Unity 開発ガイドの一部です。 ここから、次の構成要素を続けることができます。

または、Mixed Reality プラットフォームの機能と API に移動します。

いつでも Unity 開発チェックポイントに戻ることができます。

関連項目