目でサポートされるターゲットの選択 — MRTK2
このページでは、MRTK でターゲットを選択するために、目の視線入力データと目の視線入力固有のイベントにアクセスする際のさまざまなオプションについて説明します。 視線追跡を使用すると、ユーザーが何を見ているかに関する情報と、"ハンド トラッキング" や "音声コマンド" などの追加の入力を組み合わせて、すばやく容易にターゲットを選択できます。
- "選択" と & 見る (既定の音声コマンド)
- [展開] または [ポップ] (カスタム音声コマンド) と & 表示する
- Bluetooth ボタン & 見る
- ピンチ & 見る (つまり、目の前で手を上げ、親指と人差し指を一緒に持ち込む)
- これを機能させるには、ハンド レイを無効にする必要があることに注意してください
目の視線入力を使用してホログラフィック コンテンツを選択するには、いくつかのオプションがあります。
これは、優先されるカーソルだと理解できます。 既定では、視野内に手がある場合、これはハンド レイになります。 視野内に手がなければ、優先されるポインターは頭または目の視線入力になります。 そのため、ハンド レイが使用される場合は、現在の設計の頭または目の視線入力は、カーソル入力としては抑制されることに注意してください。
次に例を示します。
ユーザーは、離れたホログラフィック ボタンを選択したいと考えています。 開発者は、ユーザーがさまざまな状況でこのタスクを達成できるようにする、柔軟性のあるソリューションを提供する必要があります。
- ボタンに歩み寄って突く
- 離れてそれを見て、"選択" と言う
- ハンド レイを使用してボタンをターゲットにして、ピンチを実行する。この場合、最も柔軟性のあるソリューションは、プライマリ フォーカス ハンドラーを使用することです。それによって、現在優先されているプライマリ フォーカス ポインターによってイベントがトリガーされるたびに通知が行われるためです。 ハンド レイが有効になっている場合は、手が視野に入るとすぐに、頭や目の視線入力のフォーカス ポインターが無効にされることに注意してください。
重要
ハンド レイが有効になっている場合は、手が視野に入るとすぐに、頭や目の視線入力のフォーカス ポインターが無効にされることに注意してください。 "見てピンチする" 対話式操作をサポートする場合は、ハンド レイを無効にする必要があります。 視線追跡サンプル シーンでは、目と手の動きを併用する、より豊かな対話式操作を示すために、ハンド レイを無効にしています。たとえば、視線対応の配置に関するページを参照してください。
特定のイベントをトリガーできるのはどの種類のフォーカス ポインターであるかをより明確にして、遠隔対話式操作の手法を複数同時に使用できるようにしたい場合もあります。
例: ユーザーはアプリで遠くのハンド レイを使用して、機械的なホログラフィック設定の一部を操作できます。たとえば、離れたいくつかのホログラフィック エンジン パーツをつかんで保持し、それらを所定の位置に保持できます。 そうしている間、ユーザーはいくつかの手順を実行し、いくつかのチェック ボックスをオンにして進行状況を記録する必要があります。 ユーザーの手が "使用中でない" 場合は、本能的に、チェック ボックスに触れるか、ハンド レイを使用してそれを選択するだけです。 ただし、いくつかのホログラフィック エンジン パーツを所定の位置に保持しているこの場合のように、ユーザーの手がふさがっている場合は、ユーザーが目の視線入力を使って命令を連続的にスクロールし、チェック ボックスを見て "それをオンにする" と言うだけで済むようにする必要があります。
これを可能にするには、コアの MRTK FocusHandlers から独立している、視線専用の EyeTrackingTarget スクリプトを使用する必要があります。ついて詳しくは、以下で説明します。
1. 汎用のフォーカスとポインター ハンドラーを使用する
視線追跡が適切に設定されている場合 (視線追跡を使用するための基本的な MRTK 設定に関するページを参照)、ユーザーが視線を使ってホログラムを選択できるようにすることは、他のどのフォーカス入力 (頭の視線入力やハンド レイなど) の場合とも同様です。これによる大きな利点は、現状のコードに触れることなく、ユーザーのニーズに応じて MRTK 入力ポインター プロファイルで主なフォーカスの種類を定義することで、ホログラムを柔軟な方法で操作できることです。 これにより、コードの行に変更を加えたり、離れた対話式操作のためにハンド レイを目のターゲット設定に置き換えたりすることなく、頭と目の視線入力を切り替えることができます。
ホログラムへのフォーカスの配置
ホログラムにフォーカスが置かれたことを検出するには、OnFocusEnter と OnFocusExit という 2 つのインターフェイス メンバーがある "IMixedRealityFocusHandler" インターフェイスを使用します。
次に、ホログラムが見られたときに色を変える、ColorTap.cs からの簡単な例を示します。
public class ColorTap : MonoBehaviour, IMixedRealityFocusHandler
{
void IMixedRealityFocusHandler.OnFocusEnter(FocusEventData eventData)
{
material.color = color_OnHover;
}
void IMixedRealityFocusHandler.OnFocusExit(FocusEventData eventData)
{
material.color = color_IdleState;
}
...
}
フォーカスが置かれたホログラムの選択
フォーカスが置かれたホログラムを選択するには、PointerHandler を使用して入力イベントをリッスンし、選択を確認します。 たとえば、IMixedRealityPointerHandler を追加すると、それらは単純なポインター入力に反応するようになります。 IMixedRealityPointerHandler インターフェイスには、3 つのインターフェイス メンバー OnPointerUp、OnPointerDown、OnPointerClicked を実装する必要があります。
下の例では、ホログラムを見て、ピンチするか、"選択" と言うことによって、その色を変更しています。
イベントをトリガーするために必要なアクションは、Unity エディターで eventData.MixedRealityInputAction == selectAction
によって定義されます。ここでは selectAction
の型を設定でき、既定では、"Select" アクションです。 使用できる MixedRealityInputActions の種類は、MRTK プロファイルの、[MRTK Configuration Profile] ->[Input] ->[Input Actions] で構成できます。
public class ColorTap : MonoBehaviour, IMixedRealityFocusHandler, IMixedRealityPointerHandler
{
// Allow for editing the type of select action in the Unity Editor.
[SerializeField]
private MixedRealityInputAction selectAction = MixedRealityInputAction.None;
...
void IMixedRealityPointerHandler.OnPointerUp(MixedRealityPointerEventData eventData)
{
if (eventData.MixedRealityInputAction == selectAction)
{
material.color = color_OnHover;
}
}
void IMixedRealityPointerHandler.OnPointerDown(MixedRealityPointerEventData eventData)
{
if (eventData.MixedRealityInputAction == selectAction)
{
material.color = color_OnSelect;
}
}
void IMixedRealityPointerHandler.OnPointerClicked(MixedRealityPointerEventData eventData) { }
}
目の視線入力固有の BaseEyeFocusHandler
目の視線入力は、その他のポインター入力とは大きく異なる場合があることを考えれば、フォーカスの入力が "目の視線入力" で、それが現在プライマリ入力ポインターになっている場合にのみ入力に反応する設定にすることをお勧めします。
この目的のためには、目の視線追跡に固有で、BaseFocusHandler
から派生している BaseEyeFocusHandler
を使用します。
既に触れたように、これがトリガーされるのは、目の視線入力によるターゲット設定が、現在主なポインター入力になっている (つまり、ハンド レイがアクティブでない) 場合のみです。 詳細については、目の視線入力と手のジェスチャをサポートする方法に関するページを参照してください。
ここで、EyeTrackingDemo-03-Navigation
(Assets/MRTK/Examples/Demos/EyeTracking/Scenes) からの例を示します。
このデモには、オブジェクトのどの部分が見られているかに応じて回転する 3D ホログラムが 2 つあります。ユーザーがホログラムの左側を見ると、その部分が、ユーザーと向き合う正面に向かってゆっくりと移動します。
右側を見ると、その部分がゆっくりと正面に移動します。
これは、常時にアクティブにはしない方がよい場合もある動作で、ハンド レイや頭の視線入力によって誤ってトリガーされないようにしたい動作でもあります。
OnLookAtRotateByEyeGaze
がアタッチされていると、GameObject オブジェクトは、見られている間は回転します。
public class OnLookAtRotateByEyeGaze : BaseEyeFocusHandler
{
...
protected override void OnEyeFocusStay()
{
// Update target rotation
RotateHitTarget();
}
...
///
/// This function computes the rotation of the target to move the currently
/// looked at aspect slowly to the front.
///
private void RotateHitTarget()
{
// Example for querying the hit position of the eye gaze ray using EyeGazeProvider
Vector3 TargetToHit = (this.gameObject.transform.position - InputSystem.EyeGazeProvider.HitPosition).normalized;
...
}
}
BaseEyeFocusHandler
の使用可能なイベントの完全な一覧については、API のドキュメントを参照してください。
- OnEyeFocusStart: 目の視線入力のレイが、このターゲットのコライダーと "交差し始める" とトリガーされます。
- OnEyeFocusStay: 目の視線入力のレイが、このターゲットのコライダーと "交差している間" にトリガーされます。
- OnEyeFocusStop: 目の視線入力のレイが、このターゲットのコライダーとの "交差を終える" とトリガーされます。
- OnEyeFocusDwell: 目の視線入力のレイが、このターゲットのコライダーとの交差を終えて、指定された時間が経過するとトリガーされます。
2. 独立した視線入力固有の EyeTrackingTarget
最後に、EyeTrackingTarget
スクリプトを使用して、他のフォーカス ポインターから完全に独立した、目に基づく入力を処理できるソリューションを紹介します。
これには、3 つの "利点" があります。
- ホログラムが、ユーザーの目の視線入力にのみ反応していることを確認できます。
- これは、現在アクティブなプライマリ入力から独立しています。 そのため、複数の入力を一度に処理できます。たとえば、高速な目のターゲット設定を、手のジェスチャと組み合わせます。
- Unity エディター内から、またはコードにより、既存の動作の処理と再利用をすばやく便利に行えるように、いくつかの Unity イベントが既に設定されています。
いくつかの "短所" もあります。
- 別個の入力を個々に処理するために作業が増加します。
- 低下が極端です。目のターゲット設定だけがサポートされます。 視線追跡が機能していない場合は、何らかの追加のフォールバックが必要になります。
BaseFocusHandler と同様に、EyeTrackingTarget には、UNITY エディター (次の例を参照) で、またはコードで AddListener() を使用して便利にリッスンすることができる、目の視線入力固有の UNITY イベントがいくつか用意されています。
- OnLookAtStart()
- WhileLookingAtTarget()
- OnLookAway()
- OnDwell()
- OnSelected()
以下では、EyeTrackingTarget の使用方法について、いくつかの例を紹介します。
例 1: 視線対応のスマート通知
(Assets/MRTK/Examples/Demos/EyeTracking/Scenes) で EyeTrackingDemo-02-TargetSelection
、目の視線入力に反応する "スマートな注意深い通知" の 例を見つけることができます。
これらは、シーン内に配置できる 3D テキスト ボックスであり、見られているときには、読みやすくなるように、スムーズに拡大され、ユーザーに向けて回転されます。 ユーザーが通知を読んでいる間は、情報の表示が、鮮明でくっきりと保たれます。 通知を読んで視線をそらすと、通知は自動的に破棄され、フェードアウトされます。このすべてを実現するため、以下のような、視線追跡に固有ではない汎用の動作スクリプトがいくつか用意されています。
この方法の利点は、さまざまなイベントで同じスクリプトを再利用できることです。 たとえば、音声コマンドに基づいて、または仮想ボタンを押した後に、ホログラムをユーザーに向け始めることができます。 これらのイベントをトリガーするには、実行する必要のあるメソッドを、GameObject オブジェクトにアタッチされる EyeTrackingTarget
スクリプトで参照するだけで済みます。
"気が利くスマート通知" の例では、以下のことが行われます。
OnLookAtStart(): 次のことが始まります。通知が...
- FaceUser.Engage: ... ユーザーに向けて回転され、
- ChangeSize.Engage: ... サイズが拡大されます (指定された最大スケールまで)。
- BlendOut.Engage: ... さらにブレンドインが始められます (わずかなアイドル状態が続いた後)。
OnDwell(): 通知が十分に見られたことが、BlendOut スクリプトに通知されます。
OnLookAway(): 次のことが始まります。通知が...
- FaceUser.Disengage: ... 元の向きに戻されます。
- ChangeSize.Disengage: ... 元のサイズに縮小されます。
- BlendOut.Disengage: ... ブレンドアウトが始められます。OnDwell() がトリガーされた場合は、完全にブレンドアウトされます。それ以外の場合は、アイドル状態に戻されます。
設計上の考慮事項: ここで楽しいエクスペリエンスを実現する鍵となるのは、ユーザーの目の視線入力には常に速すぎるほどの反応をすることで、これらの動作すべての速度を慎重に調整し、不快感が生じないようにすることです。 そうしないと、これがすぐに、非常に耐えがたく感じられる可能性があります。
例 2: ホログラフィックの宝石が、見られているときにゆっくりと回転する
例 1 と同様に、EyeTrackingDemo-02-TargetSelection
(Assets/MRTK/Examples/Demos/EyeTracking/Scenes) シーン内に、ホログラフィックの宝石のホバー フィードバックを簡単に作成できます。宝石は、見られているときに (前記の回転の例とは対照的に) 一定の方向に一定の速度でゆっくりと回転します。 必要なのは、EyeTrackingTarget の WhileLookingAtTarget() イベントから、ホログラフィックの宝石の回転をトリガーすることだけです。 追加の詳細情報を以下にいくつか示します。
アタッチ先の GameObject を回転させるパブリック関数が含まれる汎用スクリプトを作成します。 次に、RotateWithConstSpeedDir.cs の例を示します。この例では、Unity エディターから、回転の方向と速度を調整できます。
using UnityEngine; namespace Microsoft.MixedReality.Toolkit.Examples.Demos.EyeTracking { /// <summary> /// The associated GameObject will rotate when RotateTarget() is called based on a given direction and speed. /// </summary> public class RotateWithConstSpeedDir : MonoBehaviour { [Tooltip("Euler angles by which the object should be rotated by.")] [SerializeField] private Vector3 RotateByEulerAngles = Vector3.zero; [Tooltip("Rotation speed factor.")] [SerializeField] private float speed = 1f; /// <summary> /// Rotate game object based on specified rotation speed and Euler angles. /// </summary> public void RotateTarget() { transform.eulerAngles = transform.eulerAngles + RotateByEulerAngles * speed; } } }
下のスクリーンショットに示すように、ターゲットの GameObject に
EyeTrackingTarget
スクリプトを追加し、UnityEvent トリガー内で RotateTarget() 関数を参照します。
例 3: それらの宝石をポップする (爆発させる) (マルチモーダルの目の視線入力に対応するターゲット選択)
前の例では、ターゲットが見られているかどうかを検出することがいかに簡単であるかと、それに対する反応をトリガーする方法を示しました。 次に、EyeTrackingTarget
の OnSelected() イベントを使用して宝石を爆発させましょう。 興味深い部分は、"どのように" 選択がトリガーされるかです。
EyeTrackingTarget
を使用すると、選択を呼び出す異なる方法をすばやく割り当てることができます。
ピンチ ジェスチャ: [Select Action] を [Select] に設定すると、選択をトリガーするために既定の手のジェスチャが使用されます。 これは、ユーザーは単に手を上げて親指と人差し指をピンチすれば、選択を確認できることを意味します。
"選択" と言う: ホログラム選択用の既定の音声コマンドである "選択" を使用します。
"爆発" または "ポップ" と言う: カスタム音声コマンドを使用するには、2 つの手順に従う必要があります。
"DestroyTarget" などのカスタム アクションを設定します
- [MRTK] -> [Input] -> [Input Actions] と移動します
- [Add a new action] をクリックします
"爆発" や "ポップ" など、このアクションをトリガーする音声コマンドを設定します
- [MRTK] -> [Input] -> [Speech] と移動します
- [Add a new speech command] をクリックします
- 作成したばかりのアクションを関連付けます
- ボタンの押下によってアクションをトリガーできるように、KeyCode を割り当てます
宝石は選択されると爆発し、音を立てて消えます。 これは HitBehaviorDestroyOnSelect
スクリプトによって処理されます。 2 つのオプションがあります。
- Unity エディターの場合: それぞれの宝石テンプレートにアタッチされるスクリプトを、Unity エディターで OnSelected() Unity イベントにリンクするだけです。
-
コードの場合: GameObjects オブジェクトをあちこちにドラッグ アンド ドロップしたくない場合は、単純に、イベント リスナーをスクリプトに直接追加することもできます。
以下に、HitBehaviorDestroyOnSelect
スクリプトでそれをどのように行ったかの例を示します。
/// <summary>
/// Destroys the game object when selected and optionally plays a sound or animation when destroyed.
/// </summary>
[RequireComponent(typeof(EyeTrackingTarget))] // This helps to ensure that the EyeTrackingTarget is attached
public class HitBehaviorDestroyOnSelect : MonoBehaviour
{
...
private EyeTrackingTarget myEyeTrackingTarget = null;
private void Start()
{
myEyeTrackingTarget = this.GetComponent<EyeTrackingTarget>();
if (myEyeTrackingTarget != null)
{
myEyeTrackingTarget.OnSelected.AddListener(TargetSelected);
}
}
...
///
/// This is called once the EyeTrackingTarget detected a selection.
///
public void TargetSelected()
{
// Play some animation
// Play some audio effect
// Handle destroying the target appropriately
}
}
例 4: ハンド レイと目の視線入力を一緒に使用する
ハンド レイは、頭と目の視線入力によるターゲット設定よりも優先されます。 これは、ハンド レイが有効になっている場合、手が視野に入った瞬間に、ハンド レイがプライマリ ポインターとして機能することを意味します。 ただし、ユーザーが特定のホログラムを見ているかどうかを検出しながらハンド レイを使用したい状況も存在する場合があります。 簡単です。 基本的に、必要なのは 2 つの手順です。
1. ハンド レイを有効にする: ハンド レイを有効にするには、[Mixed Reality Toolkit] -> [Input] -> [Pointers] と移動します。 EyeTrackingDemo-00-RootScene で、すべての視線追跡デモ シーンに対して Mixed Reality Toolkit が 1 回構成されている場合は、EyeTrackingDemoPointerProfile が表示されます。 新しい "入力プロファイル" を最初から作成することも、現在の視線追跡プロファイルを修正することもできます。
- ゼロから:: [Pointers] タブで、コンテキスト メニューから [DefaultMixedRealityInputPointerProfile] を選択します。 これは、既にハンド レイが有効になっている既定のポインター プロファイルです。 既定のカーソル (不透明な白い点) を変更するには、単にプロファイルを複製し、独自のカスタム ポインター プロファイルを作成します。 次に、Gaze Cursor Prefab の下で、DefaultCursorを EyeGazeCursor に置き換えます。
-
既存の EyeTrackingDemoPointerProfile を基にする:EyeTrackingDemoPointerProfile をダブルクリックし、Pointer Options の下で以下のエントリを追加します。
- Controller Type: "Articulated Hand"、"Windows Mixed Reality"
- Handedness: Any
- Pointer Prefab: DefaultControllerPointer
2. 見られているホログラムを検出する: 前述したように、EyeTrackingTarget
スクリプトを使用して、見られているホログラムを検出できるようにします。 ヒントを得るため、FollowEyeGaze
サンプル スクリプトに目を通すこともできます。そこでは、ハンド レイが有効になっているかどうかにかかわらず、目の視線 (カーソルなど) を追うホログラムが紹介されているためです。
これで、視線追跡デモ シーンを開始すると、自分の手から光が出てくるように表示されます。 たとえば、視界追跡ターゲット選択のデモでは、半透明の円が引き続きユーザーの目の視線入力に追従し、見られているかどうかに宝石が反応します。一方、上部のシーン メニュー ボタンでは、代わりにプライマリ入力ポインター (ユーザーの手) が使用されます。