ハンド メニュー — MRTK3

ハンド メニュー

ハンド メニューを使用すると、ユーザーは頻繁に使用される関数に対して、手動でアタッチされた UI を表示できます。 これらは通常、クイック アクションを提供する小さな ボタン グループ です。 ただし、情報や設定を表示するためのより複雑なレイアウトがハンド メニューとしてユーザーに提供される場合があります。多くの場合、手からメニューを "破棄" して世界に固定するオプションがあります。

[ハンド] メニューには、[フラット ハンドが必要] オプションと [視線入力のアクティブ化を使用する] オプションが用意されており、他のオブジェクトとの対話中に誤ったアクティブ化を防ぐことができます。 これらのオプションを使用して、不要なアクティブ化を防ぐことをお勧めします。

シーンとプレハブの例

テンプレート プロジェクトを使用している場合は、 HandMenuExamples.unity すべてスクリプトを使用してハンド メニューのいくつかの一般的な構成を HandConstraintPalmUp 示します。

ハンド メニューのサンプル シーン

HandMenuLarge

このプレハブは、長い対話時間を必要とする大規模または複雑な UI の例を示しています。 この種類の UI では、使いやすさを向上させ、腕の疲労を回避するために、手動ドロップでメニューをワールド ロックすることをお勧めします。 この例では、メニューをワールド ロックするための "グラブアンドプル" もサポートしています。

この例では、 OnFirstHandDetected() イベントで MenuContent オブジェクトをアクティブ化することで、メニューが表示され、非表示になります。 OnLastHandLost() イベントを使用すると、閉じるボタンがアクティブになり、配置アニメーションがトリガーされます。 アニメーションは単純なスケーリングの変動です。 OnLastHandLost() イベントで MenuContent を非表示にしていないため、手が表示されない場合、メニューは自動的にワールドロックされます。 [Palm Up]\(パームアップ\) セクションの値は、手のドロップでドラッグしすぎることなく、メニューをワールドロックするように最適化されています。

ハンド メニューの例 大 1

Palm Up の構成

次の使用例は、メニューの下部領域にグラブ可能なバーと自動ワールド ロック動作を提供します。 ユーザーは、手からメニューを明示的にデタッチし、これをつかんで世界に配置できます。 これを実現するために、ObjectManipulator の ManipulationStarted() イベントで SolverHandler.UpdateSolvers を無効にします。 それ以外の場合、HandConstraint ソルバーはメニューを手の位置の近くに配置しようとするため、メニューをデタッチできません。 また、HandConstraintPalmUp.StartWorldLockReattachCheckCoroutine を使用して、ユーザーが手を上げてメニューを手に再アタッチできるようにします。

ハンド メニューの例 大 2

最後に、閉じるボタンで SolverHandler.UpdateSolvers を再アクティブ化して、HandConstraint ソルバーの機能を復元する必要があります。

ハンド メニューの例 大 3

スクリプト

この HandConstraint の動作では、手で制約されるコンテンツ (ハンド UI、メニューなど) で追跡対象のオブジェクトを安全な領域に制約するソルバーが提供されます。安全な領域は、手と交差しない領域と見なされます。 手のひらがユーザーの方を向いているときに、ソルバーの追跡対象のオブジェクトをアクティブ化する一般的な動作を示すために、HandConstraintPalmUp と呼ばれる HandConstraint の派生クラスも含まれています。

その他のドキュメントについては、各 HandConstraint プロパティで使用できるツールヒントを参照してください。 いくつかのプロパティについては、以下で詳しく説明します。

  • [セーフ ゾーン]: セーフ ゾーンは、手の上でコンテンツを拘束する場所を指定します。 手との重なりを避け、対話品質を向上させるために、コンテンツを Ulnar 側に配置することをお勧めします。 安全ゾーンは、カメラのビューに直交する平面に投影された手の向きと、手の周りの境界ボックスに対するレイキャストによって計算されます。 セーフ ゾーンは、 で XRNode動作するように定義されます。 各セーフ ゾーンが異なるコントローラーの種類で何を表しているのかを調することをお勧めします。

  • カメラに向かうまで手を追う このアクティブな場合、カメラに向いているときにメニューが視線入力に十分に合わせるまで、ソルバーは手の回転に従います。 この作業を行うには、ソルバーの角度がSolverRotationBehaviorHandConstraintSolver変化するにつれてGazeAlignment、 の を から LookAtTrackedObjectLookAtMainCamera変更します。

ハンド メニューのセーフ ゾーンの例

  • アクティブ化イベント: 現在、 HandConstraint 4 つのアクティブ化イベントがトリガーされます。 これらのイベントは、さまざまな組み合わせで使用して、一意 HandConstraint の動作を作成できます。

    • OnHandActivate: 手が IsHandActive メソッドを満たしたときにトリガーします。
    • OnHandDeactivate: IsHandActive メソッドを満たされなくなったときにトリガーします。
    • OnFirstHandDetected: ハンド トラッキングの状態が、ビュー内の手からビューの最初のハンドに変わるときに発生します。
    • OnLastHandLost: ハンド追跡状態が、少なくとも 1 つのハンドからビュー内のハンドに変わるときに発生します。
  • ソルバーのアクティブ化/非アクティブ化ロジック: 現在、ロジックをアクティブ化および非アクティブ化HandConstraintPalmUpするための推奨事項は、オブジェクトを無効または有効にするのではなく、 のUpdateSolver値を使用SolverHandlerして行うことです。 これは、アタッチされたメニューの ManipulationHandler "OnManipulationStarted/Ended" イベントの後にトリガーされるエディター ベースのフックにより、サンプル シーンで確認できます。

    • 手制約ロジックの停止: ハンド制約付きオブジェクトを停止するように設定する (アクティブ化/非アクティブ化ロジックを実行しない) 場合は、HandConstraintPalmUp を無効にするのではなく、UpdateSolver を False に設定します。
      • 視線入力ベースの (または非視線入力ベースの) 再アタッチ ロジックを有効にする場合は、その後に 関数を HandConstraintPalmUp.StartWorldLockReattachCheckCoroutine() 呼び出します。 これにより、"IsValidController" 条件が満たされた場合に引き続きチェックするコルーチンがトリガーされ、一度 (またはオブジェクトが無効になった場合) に UpdateSolver が True に設定されます。
    • 手制約ロジックの開始: 手の制約付きオブジェクトを設定して (アクティブ化条件を満たしているかどうかに基づいて) 手の後を再び開始する場合は、SolverHandler の UpdateSolver を true に設定します。
  • ロジックの再アタッチ: 現在、HandConstraintPalmUp' が True であるかどうかに関係なく、 は追跡対象のポイントにターゲット オブジェクトを自動的にSolverHandlerUpdateSolver再アタッチできます。 これは、ワールドロックされた後に の StartWorldLockReattachCheckCoroutine() 関数を呼び出HandConstraintPalmUpすことによって行われます (この場合、SolverHandler の UpdateSolver を実質的に False に設定します)。