本文說明如何在實務中配置並回應指標輸入。 若想更深入了解如何在高階上控制多個指標,請參閱 指標架構。
當偵測到新控制器時,指標會在執行時自動實例化。 控制器可以連接多個指標。 例如,預設指標設定檔中,Windows Mixed Reality 控制器分別有線條和拋物線指標用於正常選擇和傳送。
指標配置
指標透過 MRTK MixedRealityPointerProfile作為輸入系統的一部分配置。 此類配置檔會在 MRTK 配置檢查器中分配給 a MixedRealityInputSystemProfile 。 指標設定檔決定游標、執行時可用的指標類型,以及這些指標如何相互通訊以決定哪一個是啟用的。
指向範圍(Pointing Extent) -定義指標與遊戲物件互動的最大距離。
指向射線投射層遮罩(Orienting Raycast Layer Masks) -這是一個優先排序的層遮罩陣列,用來決定任何指標可以互動的遊戲物件(GameObjects)以及嘗試互動的順序。 這有助於確保指標先與 UI 元素互動,再進行其他場景物件。
指標選項配置
預設的 MRTK 指標配置檔包含以下指標類別及相關的預製件。 系統執行時可用的指標清單定義在指標設定檔中的 指標選項 中。 開發者可以利用此清單重新配置現有指標、新增指標或刪除指標。
每個指標條目由以下資料集合定義:
控制器類型 -指標有效的控制器集合。
- 例如, PokePointer 負責用手指「戳」物件,預設只支援可動手控制器類型。 指標僅在控制器可用時實例化,特別是 控制器類型 定義了可用哪些控制器來建立此指標預製件。
慣用性 - 允許指向只針對特定手型 (左右)
注意事項
將指標條目的 Handedness 屬性設為 None ,實際上會讓該指標從系統中停用,作為移除該指標的替代方案。
- 指標預製 件 - 當符合指定控制器類型與慣用性開始追蹤時,此預製資產將被實例化。
控制器可以同時擁有多個指標。 例如,在 (Assets/MRTK/SDK/Profiles/HoloLens2/) 中 DefaultHoloLens2InputSystemProfile ,可動手控制器會與 PokePointer、 GrabPoint 以及 DefaultControllerPointer (,也就是手部光線) 。
注意事項
MRTK 提供一組指標預製件,分別在 Assets/MRTK/SDK/Features/UX/Prefabs/指標中。 只要包含 Assets/MRTK/SDK/Features/UX/Scripts/Pointers 或其他實作 IMixedRealityPointer腳本中的指標腳本,就可以建立新的自訂預製件。
游標配置
凝視游標可直接透過 GazeCursorPrefab 編輯器內的 MixedRealityInputSystemProfile 屬性設定。 要設定其他指標所用的游標,你需要更改對應BaseControllerPointer指標欄位中使用CursorPrefab的預製件。 若要程式化更改游標,請修改 BaseCursor 對應 IMixedRealityPointer 行為的屬性。
請參考我們在 資產/MRTK/SDK/功能/UX/預製件/游標 中的游標預製件,例如游標行為的實作。 特別是, DefaultGazeCursor 提供了根據上下文狀態改變游標圖形的穩健實作。
預設指標類別
以下類別為預設 MRTK 指標配置檔 中可用且定義的現成類別。 每個在 資產/MRTK/SDK/功能/UX/預製件/指標 下提供的指標預製件,都包含一個附帶的指標元件。
遠指標
LinePointer
LinePointer 是一個基礎指標類別,從輸入 (來源(也就是控制器的) 向指標方向繪製一條線,並支援該方向投射單一光線。 一般來說,子類別如 和 ShellHandRayPointer 傳送指標會被實例化並利用 (,這些類別也會畫線表示傳送最終會落在哪裡) ,而非這個主要提供共通功能的類別。
對於像 Oculus、Vive 和 Windows Mixed Reality 這類動態控制器,旋轉會與控制器的旋轉相匹配。 對於像 HoloLens 2 這類關節手控制器,旋轉會符合系統提供的手部指向姿勢。
CurvePointer
CurvePointer 擴展了 LinePointer 類別,允許沿曲線進行多步射線投射。 這個基礎指標類別對於曲線實例非常有用,例如傳送指標,當直線持續彎曲成拋物線時。
ShellHandRayPointer
ShellHandRayPointinter 的實作(從 延伸至 LinePointer)被用作 MRTK 指標配置檔的預設。
DefaultControllerPointer 預製件實作了這個ShellHandRayPointer類別。
GGVPointer
GGVPointer 也稱為 凝視/手勢/語音 (GGV) 指標,主要透過凝視與空中點擊或凝視與語音選擇互動,提供類似 HoloLens 1 的視角與點擊互動。 GGV 指標的位置與方向由頭部的位置與旋轉驅動。
TouchPointer
TouchPointer 負責處理 Unity Touch 輸入 (也就是觸控螢幕) 。 這些被稱為「遠距離互動」,因為觸碰螢幕的行為會將光線從攝影機投射到場景中可能較遠的位置。
MousePointer
MousePointer 為遠端互動提供螢幕對世界射線投射的動力,但用於滑鼠而非觸控。
注意事項
MRTK 預設不支援滑鼠,但可透過在 MRTK 輸入設定檔中新增 Input MouseDeviceManagerData Provider,並將 指派MixedRealityMouseInputProfile給該資料提供者來啟用。
近指標
PokePointer
PokePointer 用於與支援「近乎可觸摸互動」的遊戲物件互動。 這些都是帶有附加 NearInteractionTouchable 腳本的 GameObject。 以 UnityUI 為例,這個指標會尋找 NearInteractionTouchableUnityUIs。 PokePointer 使用 SphereCast 來判斷最近的可觸碰元素,並用來驅動像是可按按鈕這類的裝置。
在用元件 NearInteractionTouchable 設定 GameObject 時,務必設定 localForward 參數指向按鈕或其他物件前方,該物件應該可觸控。 同時也要確保可觸碰物體的 界限 與可觸碰物體的範圍相符。
實用的戳針屬性:
- 可觸及距離:可觸面可互動的最大距離
- 視覺效果:遊戲物件預設) 用於渲染指尖 (戒指的視覺效果。
- 線條:可選從指尖繪製到主動輸入表面的線條。
-
Poke Layer Masks - 一個優先排序的 LayerMask 陣列,用來決定指標可以互動的 GameObjects 及嘗試的互動順序。 請注意,GameObject 也必須有
NearInteractionTouchable元件才能與 poke 指標互動。
SpherePointer
SpherePointer 使用 UnityEngine.Physics.OverlapSphere 來識別最近的NearInteractionGrabbable互動物件,這對於ManipulationHandler像 . 與函數對類似 PokePointer/NearInteractionTouchable ,為了與球體指標互動,遊戲物件必須包含一個作為 NearInteractionGrabbable 腳本的元件。
球體指標的實用特性:
- 球體投射半徑:用於查詢可抓取物件的球體半徑。
- 近距離物件邊距:用來查詢物件是否靠近指標的球體投擲半徑頂部距離。 總近距離物體偵測半徑為球體投射半徑 + 近距離物體邊界
-
近物扇區角:指指標前軸繞的角度,用於查詢附近物體。 讓
IsNearObject查詢功能像錐形一樣。 預設設定為 66 度,以符合 Hololens 2 的行為
- 近物體平滑因子:用於近物體偵測的平滑因子。 若物體在近物體半徑內被偵測到,查詢半徑即變為近物體半徑 * (1 + 近物體平滑因子) ,以降低靈敏度並使物體更難離開偵測範圍。
-
抓取圖層遮罩(Grab Layer Masks) -一個優先排序的層遮罩陣列,用來決定指標可以互動的可能GameObjects,以及嘗試互動的順序。 請注意,GameObject 也必須有 a
NearInteractionGrabbable,才能與 SpherePointer 互動。注意事項
MRTK 提供的預設 GrabPointer 預製件中,空間感知層被停用。 這樣做是為了減少對空間網格進行球面重疊查詢時的效能影響。 你可以透過修改 GrabPointer 的預製件來啟用這個功能。
- 忽略不在視野 範圍內的碰撞器——是否要忽略那些可能在指標附近,但實際上不在視覺視野範圍內的碰撞器。 這可以防止誤抓,也能讓你在靠近可抓物但看不到時,手部光線會啟動。 視覺 視野 以錐形定義,取代典型的視錐體,以提升效能。 此錐體居中且方向與相機的視錐體相同,半徑等於顯示高度的一半 (或垂直視野) 。
傳送指標
-
TeleportPointer當執行動作時會提出傳送請求 (例如按下傳送按鈕) 移動使用者。 -
ParabolicTeleportPointer當執行動作時,會提出傳送請求 (即以拋物線射線射線按) 傳送按鈕以移動使用者。
混合實境平台的指標支援
下表詳述MRTK中常用平台通常使用的指標類型。 注意:這些平台可以新增不同類型的指標。 例如,你可以在 VR 上新增一個 Poke 指標或 Sphere 指標。 此外,帶有遊戲手把的 VR 裝置可以使用 GGV 指標。
| 指標 | OpenVR | Windows Mixed Reality | 全息鏡頭1 | HoloLens 2 |
|---|---|---|---|---|
| ShellHandRayPointer | 有效 | 有效 | 有效 | |
| 傳送指標 | 有效 | 有效 | ||
| GGVPointer | 有效 | |||
| 球體指標 | 有效 | |||
| 寶可指示器 | 有效 |
透過程式碼進行指標互動
指標事件介面
實作一個或多個以下介面並指派給具有 的 Collider GameObject 的 MonoBehaviour,將接收由相關介面定義的指標互動事件。
| 事件 | 描述 | 馴獸人 |
|---|---|---|
| 在焦點改變之前 / 焦點改變之前 | 同時在失去焦點的遊戲物件和每次指標改變焦點時獲得焦點的物件都被提升。 | IMixedRealityFocusChangedHandler |
| 專注 進入/退出 | 當第一個指標進入遊戲物件時,目標會獲得焦點;當最後一個指標離開時,該物件失去焦點。 | IMixedRealityFocusHandler |
| 指標向下/拖拉/向上/點擊 | 被提升以報告指示按壓、拖曳與釋放。 | IMixedRealityPointerHandler |
| 觸控啟動 / 更新 / 完成 | 由觸覺敏感的指標提出,喜歡 PokePointer 回報觸碰活動。 |
IMixedRealityTouchHandler |
注意事項
IMixedRealityFocusChangedHandler
IMixedRealityFocusHandler並且應該在它們被舉起的物體中處理。 雖然可以全域接收焦點事件,但與其他輸入事件不同,全球事件處理程序不會根據焦點阻擋接收事件 (事件會同時被全域處理程序及焦點) 中的對應物件接收。
指標輸入事件的運作
指標輸入事件會被 MRTK 輸入系統以類似 一般輸入事件的方式辨識與處理。 差別在於指標輸入事件只會由觸發該事件的指標聚焦的 GameObject 處理,以及任何全域輸入處理器。 一般輸入事件由所有活躍指標聚焦的 GameObjects 處理。
- MRTK 輸入系統會辨識輸入事件已發生
- MRTK 輸入系統會將輸入事件相關的介面函式發送給所有註冊的全域輸入處理器
- 輸入系統會決定觸發事件的指標聚焦的 GameObject 是哪個
- 輸入系統利用 Unity 的事件系統 ,為聚焦的 GameObject 上所有匹配元件觸發相關介面功能
- 若任何時候輸入事件被 標記為已使用,程序將結束,且不會再收到回調。
- 範例:實作介面
IMixedRealityFocusHandler的元件會被搜尋 GameObject 的焦點是否得益或失去焦點 - 注意:如果目前 GameObject 上找不到符合預期介面的元件,Unity 事件系統會冒泡搜尋父 GameObject。
- 範例:實作介面
- 若未註冊全域輸入處理器,且找不到符合的元件/介面的 GameObject,則輸入系統會呼叫每個備援註冊的輸入處理器
範例
以下是一個範例腳本,當指標移動或離開焦點,或指標選擇物件時,會改變附加渲染器的顏色。
public class ColorTap : MonoBehaviour, IMixedRealityFocusHandler, IMixedRealityPointerHandler
{
private Color color_IdleState = Color.cyan;
private Color color_OnHover = Color.white;
private Color color_OnSelect = Color.blue;
private Material material;
private void Awake()
{
material = GetComponent<Renderer>().material;
}
void IMixedRealityFocusHandler.OnFocusEnter(FocusEventData eventData)
{
material.color = color_OnHover;
}
void IMixedRealityFocusHandler.OnFocusExit(FocusEventData eventData)
{
material.color = color_IdleState;
}
void IMixedRealityPointerHandler.OnPointerDown(
MixedRealityPointerEventData eventData) { }
void IMixedRealityPointerHandler.OnPointerDragged(
MixedRealityPointerEventData eventData) { }
void IMixedRealityPointerHandler.OnPointerClicked(MixedRealityPointerEventData eventData)
{
material.color = color_OnSelect;
}
}
查詢指標
可以透過循環瀏覽可用的輸入來源 (即控制器與可用輸入) 來收集所有目前啟用的指標,以發現哪些指標被連接。
var pointers = new HashSet<IMixedRealityPointer>();
// Find all valid pointers
foreach (var inputSource in CoreServices.InputSystem.DetectedInputSources)
{
foreach (var pointer in inputSource.Pointers)
{
if (pointer.IsInteractionEnabled && !pointers.Contains(pointer))
{
pointers.Add(pointer);
}
}
}
主要指標
開發者可以訂閱 FocusProviders PrimaryPointerChanged 事件,當主要焦點指標改變時會收到通知。 這對於辨識使用者是否正在透過凝視、手光或其他輸入來源與場景互動非常有幫助。
private void OnEnable()
{
var focusProvider = CoreServices.InputSystem?.FocusProvider;
focusProvider?.SubscribeToPrimaryPointerChanged(OnPrimaryPointerChanged, true);
}
private void OnPrimaryPointerChanged(IMixedRealityPointer oldPointer, IMixedRealityPointer newPointer)
{
...
}
private void OnDisable()
{
var focusProvider = CoreServices.InputSystem?.FocusProvider;
focusProvider?.UnsubscribeFromPrimaryPointerChanged(OnPrimaryPointerChanged);
// This flushes out the current primary pointer
OnPrimaryPointerChanged(null, null);
}
PrimaryPointerExample (Assets/MRTK/Examples/Demos/Input/Scenes/PrimaryPointer) 場景展示了如何使用 PrimaryPointerChangedHandler for 事件來回應新的主指標。
指標結果
指標 Result 屬性包含用於判斷焦點物件的場景查詢目前結果。 對於光線投射指標,像是預設為動態控制器、凝視輸入和手部光線建立的指標,它會包含射線投射命中的位置和法線。
private void IMixedRealityPointerHandler.OnPointerClicked(MixedRealityPointerEventData eventData)
{
var result = eventData.Pointer.Result;
var spawnPosition = result.Details.Point;
var spawnRotation = Quaternion.LookRotation(result.Details.Normal);
Instantiate(MyPrefab, spawnPosition, spawnRotation);
}
PointerResultExample場景 (Assets/MRTK/Examples/Demos/Input/Scenes/PointerResult/PointerResultExample.Unity) 展示了如何用指標Result在命中位置生成物件。
停用指標
例如,要啟用或停用 (指標,例如要關閉手部射線) ,透過 設定指定指標類型的 PointerUtils。PointerBehavior
// Disable the hand rays
PointerUtils.SetHandRayPointerBehavior(PointerBehavior.AlwaysOff);
// Disable hand rays for the right hand only
PointerUtils.SetHandRayPointerBehavior(PointerBehavior.AlwaysOff, Handedness.Right);
// Disable the gaze pointer
PointerUtils.SetGazePointerBehavior(PointerBehavior.AlwaysOff);
// Set the behavior to match HoloLens 1
// Note, if on HoloLens 2, you must configure your pointer profile to make the GGV pointer show up for articulated hands.
public void SetHoloLens1()
{
PointerUtils.SetPokePointerBehavior(PointerBehavior.AlwaysOff, Handedness.Any);
PointerUtils.SetGrabPointerBehavior(PointerBehavior.AlwaysOff, Handedness.Any);
PointerUtils.SetRayPointerBehavior(PointerBehavior.AlwaysOff, Handedness.Any);
PointerUtils.SetGGVBehavior(PointerBehavior.Default);
}
更多範例請參見PointerUtils。TurnPointersOnOff
透過編輯器進行指標互動
對於由 IMixedRealityPointerHandler處理的指標事件,MRTK 提供了額外的便利,透過 PointerHandler 元件形式,允許指標事件直接透過 Unity 事件處理。
指標範圍
遠方指標有設定限制它們射線距離及與場景中其他物件互動的距離。 預設值設為10公尺。 此數值的選擇是為了與 HoloLens 外殼的行為保持一致。
這可以透過更新 DefaultControllerPointer 預製件 ShellHandRayPointer 元件的欄位來改變:
指標範圍(Pointer Extent) -這用來控制指標互動的最大距離。
預設指標範圍 - 控制指標射線/線條在指標不互動時所渲染的長度。