本頁討論了在MRTK中選取目標的不同存取眼球凝視資料及眼球凝視特定事件的選項。 眼動追蹤結合使用者所看目標資訊,並結合手 部追蹤 和 語音指令等額外輸入,使目標選擇快速且輕鬆:
- 看 & 說 「選擇」 (預設語音指令)
- & 說 「爆炸」 或 「爆炸」 (自訂語音指令)
- 看看 & 藍牙按鈕
- 看 & 捏 (也就是把手舉到前面,拇指和食指合攏)
- 請注意,要讓這功能正常運作, 手部光線必須被關閉
要利用眼神凝視選擇全息內容,有幾個選項:
這可以理解為你優先排序的游標。 預設情況下,如果手在視野內,那就是手部光線。 如果沒有手在視野內,那麼優先指標會是頭部或眼睛凝視。 因此請注意,根據目前的設計,若使用手部光線,頭部或眼睛凝視會被抑制為游標輸入。
例如:
使用者想選擇遠方的全息按鈕。 作為開發者,你希望提供一個靈活的解決方案,讓使用者能在各種條件下完成這些任務:
- 走到按鈕前,輕按它
- 從遠處看,然後說「選擇」
- 用手射線鎖定按鈕並施壓。在這種情況下,最靈活的解決方案是使用主焦點處理器,因為它會在當前優先的主要焦點指標觸發事件時通知你。 請注意,如果啟用手部光線,頭部或眼睛凝視的對焦指標會在雙手進入視野時立即關閉。
重要事項
請注意,如果啟用手部光線,頭部或眼睛凝視的對焦指標會在雙手進入視野時立即關閉。 如果你想支援 「看了就捏」 的互動,你需要關閉手部射線。 在我們的眼動追蹤範例場景中,我們關閉了手部光線,以便透過眼睛+手部動作展現更豐富的互動——例如參見 眼部支持定位(Eye-Supported Positioning)。
有些情況你可能想更具體說明哪種焦點指標能觸發特定事件,並允許同時使用多種遠距離互動技術。
舉例來說:在你的應用程式中,使用者可以用遠手射線來操控某些全息機械裝置——例如,抓取並持有一些遠處的全息引擎零件並將其固定在原位。 在此過程中,使用者必須完成多項指示,並透過勾選一些勾選框來記錄進度。 如果使用者 手不忙,通常會本能地輕觸勾選框或用手部光線選擇。 然而,如果使用者雙手忙碌,例如我們手中拿著全息引擎零件,你希望讓使用者能透過眼神無縫滑動說明,並只要看到勾選框說「勾選!」。
為實現此功能,您需要使用獨立於 MRTK FocusHandlers 核心的眼睛專用 EyeTrackingTarget 腳本,稍後會詳細說明。
1. 使用通用的焦點與指標處理器
如果眼動追蹤設定正確, (看到 基本MRTK設定使用眼動追蹤) ,使用者用眼睛選擇全息影像的操作方式與其他對焦輸入 (如頭部凝視或手部光線) 相同。這提供了一個靈活的互動方式,可以根據使用者需求在 MRTK 輸入指標設定檔中定義主要焦點類型,同時保持程式碼不變。 這讓人們可以在不更改程式碼的情況下切換頭部或眼睛凝視,也不必將手部光線換成眼睛目標鎖定,以進行遠距離互動。
聚焦全息影像
要偵測全息影像是否被聚焦,請使用「 IMixedRealityFocusHandler」 介面,該介面提供兩個介面成員: OnFocusEnter 和 OnFocusExit。
這裡有一個簡單的例子, 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 介面需要實作以下三個介面成員:OnPointerUp、OnPointerDown 和 OnPointerClicked。
在下面的範例中,我們透過觀察全息影像並捏住或說「選取」來改變它的顏色。
觸發事件所需的動作定義 eventData.MixedRealityInputAction == selectAction 為,我們可以在 Unity 編輯器中設定 的 selectAction 類型——預設是「Select」動作。 可用的 混合現實輸入動作 類型可透過 MRTK 配置檔 ->Input ->Input Actions 在 MRTK 設定檔中配置。
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
考慮到眼睛凝視和其他指標輸入可能差異很大,你可能要確保只有在焦點輸入是 眼睛凝視 且目前是主要輸入指標時才反應。
為此,你會使用 專屬於眼動追蹤的 , BaseEyeFocusHandler 且 是從 BaseFocusHandler衍生出來的。
如前所述,只有當眼睛凝視目標是目前主要指標輸入 (也就是沒有手部光線啟動時,) 才會觸發。 欲了解更多資訊,請參閱 「如何支持眼神凝視+手勢」。
這裡有一個來自 EyeTrackingDemo-03-Navigation (Assets/MRTK/Examples/Demo/EyeTracking/Scenes) 的範例。
在這個示範中,有兩個 3D 全息影像會根據觀察物體的哪一部分而轉動:如果使用者看向全息圖的左側,該部分會慢慢向正面移動。
如果看右側,那部分會慢慢移到前面。
這種行為你可能不希望一直保持,也不想被手射線或頭部凝視意外觸發。
有了 連接後 OnLookAtRotateByEyeGaze ,遊戲物件會在被觀看時旋轉。
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;
...
}
}
請參閱 API 文件以獲取完整的可用事件清單:BaseEyeFocusHandler
- OnEyeFocusStart: 當眼睛凝視 射線開始 與該目標的碰撞器相交時觸發。
- OnEyeFocusStay:當眼睛凝視射線與目標的碰撞器相交時觸發。
- OnEyeFocusStop: 當眼睛凝視 射線停止 與該目標的碰撞器相交時觸發。
- OnEyeFocusDwell: 當眼睛凝視射線與目標的碰撞器相交指定時間後觸發。
2. 獨立的眼球專屬眼球追蹤目標
最後,我們提供一個解決方案,讓你能完全獨立於腳本中對其他焦點指標 EyeTrackingTarget 的眼睛輸入處理。
這有三個 優點:
- 你可以確保全息影像只對使用者的眼神有反應。
- 這與當前主要輸入無關。 因此,你可以同時處理多個輸入——例如,結合快速的眼睛瞄準與手勢。
- 已經設置了多個 Unity 事件,讓在 Unity 編輯器內或程式碼中快速且方便地處理與重用現有行為。
但也有一些 缺點:
- 要花更多力氣分別處理獨立輸入。
- 沒有優雅的降級:它只支援眼睛瞄準。 如果眼動追蹤無法運作,你需要額外的備用方案。
與 BaseFocusHandler 類似, EyeTrackingTarget 內建多個專屬的 Unity 視線事件,您可以透過 Unity 編輯器 (詳見) 下方範例,方便收聽,或使用 AddListener () 程式碼中:
- 開始 ()
- 在Target ()
- 《望遠 ()
- OnDwell ()
- OnSelected ()
以下將帶你了解幾個如何使用 EyeTrackingTarget 的範例。
範例 #1:眼部支援的智慧通知
在 EyeTrackingDemo-02-TargetSelection (Assets/MRTK/Examples/Demo/EyeTracking/Scenes) ,你可以找到一個「 智慧專注通知」 的範例,這些通知會對你的眼神視線做出反應。
這些是可以放置在場景中的 3D 文字框,當使用者觀看時會平滑地放大並轉向,以提升可讀性。 當使用者閱讀通知時,資訊會持續清晰且清晰地顯示。 讀完後移開通知後,通知會自動被關閉並淡出。為了達成這些,有一些通用的行為腳本,這些腳本並非專屬於眼動追蹤,例如:
此方法的優點是相同的腳本可被不同事件重複使用。 例如,全息影像可能根據語音指令或按下虛擬按鈕後開始面向使用者。 要觸發這些事件,你可以參考綁定在 GameObject 的腳本中應該執行 EyeTrackingTarget 的方法。
以 「智慧專注通知」為例,會發生以下情況:
OnLookAtStart () :通知開始......
- FaceUser。Engage: ...轉向使用者。
- ChangeSize。Engage: ...尺寸增加 (至指定最大比例尺) 。
- BlendOut。Engage: ... 在進入較微妙的閒置狀態後,開始融入更多 () 。
OnDwell () :通知 BlendOut 腳本已充分檢視該通知。
OnLookAway () :通知開始......
- FaceUser.Disengage : ...回到原本的方向。
- 改變大小。脫落: ...縮小回原本大小。
- BlendOut.Disengage: ...開始混合——如果 OnDwell () 被觸發,請完全混合並摧毀,否則恢復閒置狀態。
設計考量: 這裡享受體驗的關鍵是謹慎調整這些行為的速度,避免因過度反應使用者的眼神而造成不適。 否則這很快就會讓人感到非常壓力山大。
範例 #2:全息寶石在看著它時旋轉緩慢
類似範例 #1,我們可以輕鬆為 (Assets/MRTK/Examples/Demo/EyeTracking/Scenes) 場景中,為全息寶石 EyeTrackingDemo-02-TargetSelection 建立懸浮回饋,這些回饋會緩慢以恆定方向和恆定速度旋轉, (與上方的旋轉範例形成對比,) 觀看時。 你只需要觸發 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; } } }將腳本加入
EyeTrackingTarget你的目標 GameObject,並在 UnityEvent 觸發器中參考 RotateTarget () 函式,如下圖所示:
範例 #3:戳破那些寶石,也就是 多模態眼神凝視支援的目標選擇
在前一個例子中,我們展示了如何判斷目標是否被注視,以及如何觸發反應是多麼容易。 接著,讓我們利用 OnSelected () 事件 EyeTrackingTarget讓寶石爆炸。 有趣的是選擇 是如何 觸發的。 此方法 EyeTrackingTarget 允許快速指派不同的方式來呼叫選擇:
捏合手勢:將「選擇動作」設為「選擇」會使用預設的手勢來觸發選擇。 這表示使用者只需舉起手,並用拇指和食指夾在一起即可確認選擇。
說 「選擇」:使用預設語音指令 「選擇」 來選擇全息影像。
說 「爆炸」 或 「爆炸」:要使用自訂語音指令,你需要遵循兩個步驟:
設定自訂動作,例如 「DestroyTarget」
- 導航至 MRTK -> 輸入 -> 輸入動作
- 點擊「新增動作」
設定觸發此動作的語音指令,例如 「爆炸」 或 「爆炸」
- 導航到 MRTK -> 輸入 -> 語音
- 點選「新增語音指令」
- 將你剛建立的動作關聯起來
- 指定 一個按鍵代碼 ,允許透過按鍵觸發動作
當選擇寶石時,寶石會爆炸並發出聲音後消失。 這由 HitBehaviorDestroyOnSelect 劇本處理。 您有兩種選擇:
- 在 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:同時使用手部光線和眼神凝視輸入
手部光線優先於頭部和眼睛凝視的鎖定。 這表示,如果啟用手部光線,當手部進入視野的那一刻,手部光線就會成為主要指標。 不過,有些情況下你可能想用手部光線,同時偵測使用者是否在看某個全息影像。 慢點! 基本上你需要兩個步驟:
1. 啟用手部光線:要啟用手部光線,請前往 Mixed Reality 工具包 -> 輸入 -> 指標。 在 EyeTrackingDemo-00-RootScene 中,Mixed Reality Toolkit 只設定一次所有眼動追蹤示範場景,你應該會看到 EyeTrackingDemoPointerProfile。 你可以從零開始建立新的 輸入設定檔 ,或是改裝目前的眼動追蹤設定檔:
- 從零開始: 在 指標 標籤中,從右鍵選單選擇 DefaultMixedRealityInputPointerProfile 。 這是預設的指標設定檔,已經啟用了手部射線! 要將預設游標 (不透明白點) ,只要複製該設定檔並建立自訂指標設定檔即可。 接著在凝視游標預製件下,將 DefaultCursor 替換成 EyeGazeCursor。
-
根據現有 的 EyeTrackingDemoPointerProfile: 雙擊 EyeTrackingDemoPointerProfile ,並在 指標選項中新增以下條目:
- 控制器類型:「關節手」、「Windows Mixed Reality」
- 慣用手: 任何
- Pointer 預製件: DefaultControllerPointer
2. 偵測到有人在看全息影像: 使用 EyeTrackingTarget 腳本來偵測到有人在看全息影像,如上所述。 你也可以參考 FollowEyeGaze 範例腳本作為靈感,因為裡面會顯示一個全息影像跟隨你的視線,例如 (游標) 是否啟用手部射線。
現在,當你開始進行眼動追蹤的示範場景時,你應該會看到手中射出光線。 例如,在眼動追蹤目標選擇示範中,半透明的圓圈仍會跟隨你的眼睛,寶石會根據是否被看而回應,而頂部場景選單按鈕則使用手 () 的主要輸入指標。