共用方式為


Interactive 元素 [實驗性] — MRTK2

MRTK 輸入系統的簡化集中式進入點。 包含狀態管理方法、事件管理和核心互動狀態的狀態設定邏輯。

Interactive Element 是 Unity 2019.3 中支援的實驗性功能,其利用 Unity 2019.3 的新功能: 序列化參考

Interactive 元素偵測器

在播放模式期間,Interactive Element Inspector 會提供視覺化回饋,指出目前狀態是否為作用中。 如果狀態為作用中,則會以青色反白顯示。 如果狀態不是使用中,則色彩不會變更。 偵測器中狀態旁的數位是狀態值,如果狀態為使用中,則值為 1,如果狀態不是作用中,則值為 0。

具有虛擬手部互動的 Interactive 元素

核心狀態

Interactive Element 包含核心狀態,並支援新增 自訂狀態。 核心狀態是已在 中 BaseInteractiveElement 定義狀態設定邏輯的狀態設定邏輯。 以下是目前輸入驅動核心狀態的清單:

目前的核心狀態

近近與遠互動核心狀態:

近互動核心狀態:

遠距互動核心狀態:

其他核心狀態:

如何透過偵測器新增核心狀態

  1. 在 Interactive 元素的偵測器中,流覽至 [ 新增核心狀態 ]。

    透過偵測器新增核心狀態

  2. 選取 [ 選取狀態 ] 按鈕,選擇要新增的核心狀態。 功能表中的狀態會依互動類型排序。

    透過已選取狀態的偵測器新增核心狀態

  3. 開啟 [事件組態] 折迭,以檢視與狀態相關聯的事件和屬性。

    使用事件設定透過偵測器新增核心狀態

如何透過腳本新增核心狀態

AddNewState(stateName)使用 方法來新增核心狀態。 如需可用核心狀態名稱的清單,請使用 CoreInteractionState 列舉。

// Add by name or add by CoreInteractionState enum to string

interactiveElement.AddNewState("SelectFar");

interactiveElement.AddNewState(CoreInteractionState.SelectFar.ToString());

狀態內部結構

Interactive 元素中的狀態類型為 InteractionStateInteractionState包含下列屬性:

  • 名稱:狀態的名稱。
  • :狀態值。 如果狀態為開啟,狀態值為 1。 如果狀態為關閉,狀態值為 0。
  • 作用中:狀態目前是否為使用中。 當狀態開啟時,Active 屬性的值為 true,如果狀態為關閉,則為 false。
  • 互動類型:狀態的互動類型是狀態所適用的互動類型。
    • None:不支援任何形式的輸入互動。
    • Near:接近互動支援。 當清楚的手部與另一個遊戲物件直接接觸時,輸入會被視為接近互動,亦即,所表達手部的位置接近世界空間中游戲物件的位置。
    • Far:遠距互動支援。 不需要與遊戲物件直接接觸時,輸入會被視為遠距互動。 例如,透過控制器光線或注視的輸入會被視為遠距互動輸入。
    • NearAndFar:包含近近和遠的互動支援。
    • Other:指標獨立互動支援。
  • 事件組態:狀態的事件組態是序列化事件設定檔進入點。

所有這些屬性都會在 State Manager Interactive Element 中包含的 內部設定。 若要修改狀態,請使用下列協助程式方法:

狀態設定協助程式方法

// Get the InteractionState
interactiveElement.GetState("StateName");

// Set a state value to 1/on
interactiveElement.SetStateOn("StateName");

// Set a state value to 0/off
interactiveElement.SetStateOff("StateName");

// Check if a state is present in the state list
interactiveElement.IsStatePresent("StateName");

// Check whether or not a state is active
interactiveElement.IsStateActive("StateName");

// Add a new state to the state list
interactiveElement.AddNewState("StateName");

// Remove a state from the state list
interactiveElement.RemoveState("StateName");

取得狀態的事件組態專屬於狀態本身。 每個核心狀態都有特定的事件組態類型,其概述于描述每個核心狀態的各節底下。

以下是取得狀態事件設定的一般化範例:

// T varies depending on the core state - the specific T's are specified under each of the core state sections
T stateNameEvents = interactiveElement.GetStateEvents<T>("StateName");

預設狀態

預設狀態一律存在於 Interactive 元素上。 只有在所有其他狀態都不是作用中時,此狀態才會處於作用中狀態。 如果任何其他狀態變成作用中,預設狀態將會設定為在內部關閉。

Interactive 元素會使用狀態清單中存在的 [預設] 和 [焦點] 狀態初始化。 預設狀態一律必須出現在狀態清單中。

取得預設狀態事件

預設狀態的事件組態類型: StateEvents

StateEvents defaultEvents = interactiveElement.GetStateEvents<StateEvents>("Default");

defaultEvents.OnStateOn.AddListener(() =>
{
    Debug.Log($"{gameObject.name} Default State On");
});

defaultEvents.OnStateOff.AddListener(() =>
{
    Debug.Log($"{gameObject.name} Default State Off");
});

焦點狀態

焦點狀態是接近且遠的互動狀態,可視為相當於暫留的混合實境。 焦點狀態的近遠互動區分因素是目前的使用中指標類型。 如果焦點狀態的指標類型是 Poke 指標,則會將互動視為接近互動。 如果主要指標不是 Poke 指標,則會將互動視為遠方互動。 根據預設,焦點狀態會出現在 Interactive 元素中。

焦點狀態行為使用虛擬手部互動的焦點狀態

Inpsector 中的焦點狀態偵測器焦點狀態

取得焦點狀態事件

焦點狀態的事件組態類型: FocusEvents

FocusEvents focusEvents = interactiveElement.GetStateEvents<FocusEvents>("Focus");

focusEvents.OnFocusOn.AddListener((pointerEventData) =>
{
    Debug.Log($"{gameObject.name} Focus On");
});

focusEvents.OnFocusOff.AddListener((pointerEventData) =>
{
    Debug.Log($"{gameObject.name} Focus Off");
});

焦點接近與焦點遠距行為

使用虛擬手部互動將焦點放在附近和遠處

焦點接近狀態

當引發焦點事件,而主要指標是 Poke 指標,即接近互動的指示時,就會設定焦點接近狀態。

焦點近點狀態行為使用虛擬手部互動將接近狀態焦點

偵測器中的焦點接近狀態偵測器焦點元件

取得 FocusNear 狀態事件

FocusNear 狀態的事件組態類型: FocusEvents

FocusEvents focusNearEvents = interactiveElement.GetStateEvents<FocusEvents>("FocusNear");

focusNearEvents.OnFocusOn.AddListener((pointerEventData) =>
{
    Debug.Log($"{gameObject.name} Near Interaction Focus On");
});

focusNearEvents.OnFocusOff.AddListener((pointerEventData) =>
{
    Debug.Log($"{gameObject.name} Near Interaction Focus Off");
});

焦點遠距狀態

當主要指標不是 Poke 指標時,就會設定焦點遠距狀態。 例如,預設控制器光線指標和 GGV (注視、手勢、語音) 指標會被視為遠距互動指標。

焦點遠距狀態行為使用虛擬手部互動的焦點狀態

偵測器中的焦點遠距偵測器焦點元件

取得焦點遠距狀態事件

FocusFar State 的事件組態類型: FocusEvents

FocusEvents focusFarEvents = interactiveElement.GetStateEvents<FocusEvents>("FocusFar");

focusFarEvents.OnFocusOn.AddListener((pointerEventData) =>
{
    Debug.Log($"{gameObject.name} Far Interaction Focus On");
});

focusFarEvents.OnFocusOff.AddListener((pointerEventData) =>
{
    Debug.Log($"{gameObject.name} Far Interaction Focus Off");
});

觸控狀態

觸控狀態是接近互動狀態,會在表達的手部直接觸碰物件時設定。 直接觸控表示已表達的手部索引指非常接近物件的世界位置。 根據預設, NearInteractionTouchableVolume 如果 Touch 狀態已新增至狀態清單,元件就會附加至 物件。 NearInteractionTouchableVolume偵測 Touch 事件需要有 或 NearInteractionTouchable 元件。 和 NearInteractionTouchable 之間的差異 NearInteractionTouchableVolume 在於會 NearInteractionTouchableVolume 根據物件的碰撞器偵測觸控,並 NearInteractionTouchable 偵測平面定義區域內的觸控。

觸控狀態行為觸控狀態與虛擬手部互動

偵測器中的觸控狀態偵測器觸控狀態元件

取得觸控狀態事件

Touch State 的事件組態類型: TouchEvents

TouchEvents touchEvents = interactiveElement.GetStateEvents<TouchEvents>("Touch");

touchEvents.OnTouchStarted.AddListener((touchData) =>
{
    Debug.Log($"{gameObject.name} Touch Started");
});

touchEvents.OnTouchCompleted.AddListener((touchData) =>
{
    Debug.Log($"{gameObject.name} Touch Completed");
});

touchEvents.OnTouchUpdated.AddListener((touchData) =>
{
    Debug.Log($"{gameObject.name} Touch Updated");
});

選取 [遠距狀態]

Select Far 狀態為 IMixedRealityPointerHandler 表面。 此狀態是一種遠距互動狀態,可偵測遠距互動點選 (點選) ,並透過使用預設控制器光線指標或 GGV 指標等遠距互動指標來保存。 Select Far 狀態在名為 Global 的事件組態折迭下方有一個選項。 如果 Global 為 true,則會 IMixedRealityPointerHandler 將 註冊為全域輸入處理常式。 如果處理常式註冊為全域,則不需要將焦點放在物件上,即可觸發輸入系統事件。 例如,如果使用者想要知道無論焦點中的物件為何,只要執行空中點選/選取手勢,請將 設定 Global 為 true。

選取 [遠方狀態行為選取遠方] 與虛擬手部互動

在偵測器中選取 [遠方狀態偵測器] 選取遠方元件

取得選取遠方狀態事件

SelectFar State 的事件組態類型: SelectFarEvents

SelectFarEvents selectFarEvents = interactiveElement.GetStateEvents<SelectFarEvents>("SelectFar");

selectFarEvents.OnSelectUp.AddListener((pointerEventData) =>
{
    Debug.Log($"{gameObject.name} Far Interaction Pointer Up");
});

selectFarEvents.OnSelectDown.AddListener((pointerEventData) =>
{
    Debug.Log($"{gameObject.name} Far Interaction Pointer Down");
});

selectFarEvents.OnSelectHold.AddListener((pointerEventData) =>
{
    Debug.Log($"{gameObject.name} Far Interaction Pointer Hold");
});

selectFarEvents.OnSelectClicked.AddListener((pointerEventData) =>
{
    Debug.Log($"{gameObject.name} Far Interaction Pointer Clicked");
});

已點選狀態

按一下狀態是由遠距互動所觸發, (預設會選取 [遠距狀態]) 。 此狀態會在內部切換為開啟,叫用 OnClicked 事件,然後立即切換為關閉。

注意

根據狀態活動在偵測器中的視覺回饋不存在,因為已開啟再立即關閉,所以按一下狀態不存在。

具有虛擬手部互動的已點選狀態已點選狀態

按一下狀態偵測器偵測器中按一下狀態元件

接近和遠點選狀態範例
按一下的狀態可以使用 方法來透過其他進入點 interactiveElement.TriggerClickedState() 觸發。 例如,如果使用者想要接近互動觸控來觸發物件的點選,他們也會將 方法新增 TriggerClickedState() 為觸控狀態的接聽程式。

使用虛擬手部互動的近遠狀態

取得點選狀態事件

按一下狀態的事件組態類型: ClickedEvents

ClickedEvents clickedEvent = interactiveElement.GetStateEvents<ClickedEvents>("Clicked");

clickedEvent.OnClicked.AddListener(() =>
{
    Debug.Log($"{gameObject.name} Clicked");
});

切換開啟和關閉狀態

[開啟開啟] 和 [切換關閉] 狀態是一對,而且兩者都需要有切換行為。 根據預設,[開啟開啟] 和 [切換關閉] 狀態會透過遠距互動按一下 ([選取遠距狀態]) 觸發。 根據預設,[切換關閉] 狀態在啟動時為作用中,這表示切換將會初始化為關閉。 如果使用者希望 [開啟開啟] 狀態在啟動時處於作用中狀態,則處於 [切換開啟] 狀態設定 IsSelectedOnStart 為 true。

ToggleOn 和切換關閉狀態行為開啟和關閉與虛擬手部互動

ToggleOn 和關閉狀態偵測器切換偵測器中的切換元件

接近和遠距切換狀態範例
與按一下狀態類似,切換狀態設定可以使用 方法有多個進入點 interactiveElement.SetToggleStates() 。 例如,如果使用者想要觸控做為額外的進入點來設定切換狀態,則他們會將 SetToggleStates() 方法新增至 Touch 狀態中的其中一個事件。

使用虛擬手部互動的近遠切換

[開啟開啟] 和 [關閉狀態事件]

ToggleOn 狀態的事件組態類型: ToggleOnEvents
ToggleOff 狀態的事件組態類型: ToggleOffEvents

// Toggle On Events
ToggleOnEvents toggleOnEvent = interactiveElement.GetStateEvents<ToggleOnEvents>("ToggleOn");

toggleOnEvent.OnToggleOn.AddListener(() =>
{
    Debug.Log($"{gameObject.name} Toggled On");
});

// Toggle Off Events
ToggleOffEvents toggleOffEvent = interactiveElement.GetStateEvents<ToggleOffEvents>("ToggleOff");

toggleOffEvent.OnToggleOff.AddListener(() =>
{
    Debug.Log($"{gameObject.name} Toggled Off");
});

語音關鍵字狀態

語音關鍵字狀態會接聽Mixed Reality語音設定檔中定義的關鍵字。 在執行時間之前,必須在語音命令設定檔中註冊任何新的關鍵字, (下列步驟) 。

具有虛擬互動的語音關鍵字語音關鍵字

Inspector 中的語音關鍵字狀態偵測器語音關鍵字元件

注意

語音關鍵字狀態是在編輯器中按下上述 gif 中的 F5 鍵來觸發。 在語音的編輯器測試中設定概述下列步驟。

如何註冊語音命令/關鍵字

  1. 選取 MixedRealityToolkit 遊戲物件

  2. 選取 [複製並自訂 目前的設定檔]

  3. 流覽至 [輸入] 區段,然後選取 [ 複製 ] 以啟用輸入設定檔的修改

  4. 向下捲動至輸入設定檔中的 [語音] 區段,並複製語音設定檔

    MRTK 遊戲物件中的語音關鍵字設定檔

  5. 選取 [新增語音命令]

    在 MRTK 設定檔中新增語音關鍵字

  6. 輸入新的關鍵字。 選擇性:將 KeyCode 變更為 F5 (或其他 KeyCode) ,以允許在編輯器中進行測試。

    在 MRTK 設定檔中設定語音關鍵字

  7. 返回至 Interactive Element Speech 關鍵字狀態偵測器,然後選取 [新增關鍵字]

    將 關鍵字新增至互動式元素元件

    關鍵字驗證和註冊

  8. 輸入剛在語音設定檔中註冊的新關鍵字

    輸入新的語音關鍵字

若要在編輯器中測試語音關鍵字狀態,請按步驟 6 中定義的 KeyCode (F5) 來模擬語音辨識的語音關鍵字事件。

取得語音關鍵字狀態事件

SpeechKeyword 狀態的事件組態類型: SpeechKeywordEvents

SpeechKeywordEvents speechKeywordEvents = interactiveElement.GetStateEvents<SpeechKeywordEvents>("SpeechKeyword");

speechKeywordEvents.OnAnySpeechKeywordRecognized.AddListener((speechEventData) =>
{
    Debug.Log($"{speechEventData.Command.Keyword} recognized");
});

// Get the "Change" Keyword event specifically
KeywordEvent keywordEvent = speechKeywordEvents.Keywords.Find((keyword) => keyword.Keyword == "Change");

keywordEvent.OnKeywordRecognized.AddListener(() =>
{ 
    Debug.Log("Change Keyword Recognized"); 
});

自訂狀態

如何透過偵測器建立自訂狀態

透過偵測器建立的自訂狀態將會使用預設狀態事件組態來初始化。 自訂狀態的預設事件組態的類型為 StateEvents ,並包含 OnStateOn 和 OnStateOff 事件。

  1. 流覽至在 Interactive 元素的偵測器中 建立自訂狀態

    建立自訂狀態

  2. 輸入新狀態的名稱。 此名稱必須是唯一的,而且不能與現有的核心狀態相同。

    輸入新自訂狀態的名稱

  3. 選取 [設定狀態名稱 ] 以新增至狀態清單。

    將自訂狀態新增至狀態清單

    這個自訂狀態會使用包含 OnStateOnOnStateOff 事件的預設 StateEvents 事件組態進行初始化。 若要建立新狀態的自訂事件組態,請參閱: 使用自訂事件組態建立自訂狀態

    互動式專案元件中顯示的新狀態

如何透過腳本建立自訂狀態

interactiveElement.AddNewState("MyNewState");

// A new state by default is initialized with a the default StateEvents configuration which contains the 
// OnStateOn and OnStateOff events

StateEvents myNewStateEvents = interactiveElement.GetStateEvents<StateEvents>("MyNewState");

myNewStateEvents.OnStateOn.AddListener(() =>
{
    Debug.Log($"MyNewState is On");
});

使用自訂事件組態建立自訂狀態

名為 Keyboard 之自訂狀態的範例檔案位於此處:MRTK\SDK\Experimental\InteractiveElement\Examples\Scripts\CustomStateExample

下列步驟會逐步解說建立自訂狀態事件組態和接收者檔案的現有範例。

  1. 想像一下狀態名稱。 此名稱必須是唯一的,而且不能與現有的核心狀態相同。 為了本範例的目的,狀態名稱將會是 Keyboard

  2. 建立兩個名為 state name + 「Receiver」 和 state name + 「Events」 的 .cs 檔案。 這些檔案的命名會在內部考慮,且必須遵循狀態名稱 + 事件/接收者慣例。

    鍵盤狀態腳本

  3. 如需檔案內容的詳細資訊,請參閱 KeyboardEvents.cs 和 KeyboardReceiver.cs 檔案。 新的事件組態類別必須繼承自 BaseInteractionEventConfiguration ,而新的事件接收者類別必須繼承自 BaseEventReceiver 。 鍵盤狀態的狀態設定範例位於 檔案中 CustomStateSettingExample.cs

  4. 使用狀態名稱將狀態新增至 Interactive Element,如果事件組態和事件接收器檔案存在,則會辨識狀態名稱。 自訂事件組態檔中的屬性應該會出現在偵測器中。

    將自訂狀態新增至 互動式元素 :互動式元素中辨識的自訂狀態

  5. 如需事件組態和事件接收者檔案的更多範例,請參閱這些路徑中的檔案:

  • MRTK\SDK\Experimental\InteractiveElement\InteractiveElement\Events\EventConfigurations
  • MRTK\SDK\Experimental\InteractiveElement\InteractiveElement\Events\EventReceivers

範例場景

Interactive Element + State Visualr 的範例場景位於此處:MRTK\SDK\Experimental\InteractiveElement\Examples\InteractiveElementExampleScene.unity

互動式元素和狀態視覺化檢視的範例場景

可壓縮按鈕

此範例場景包含名為 和 CompressableButtonToggleCompressableButton 預製專案,這些預製專案會鏡像使用 Interactive Element 和狀態視覺化檢視所建構的 PressableButtonHoloLens2 按鈕行為。 元件 CompressableButton 目前是 與 BaseInteractiveElement 做為基類的組合 + PressableButtonPressableButtonHoloLens2

狀態視覺化檢視 [實驗性]

狀態視覺化檢視元件會根據連結的 Interactive Element 元件中定義的狀態,將動畫新增至物件。 此元件會建立動畫資產、將它們放在 MixedRealityToolkit.Generated 資料夾中,並透過將 Animatable 屬性新增至目標遊戲物件來啟用簡化的動畫主要畫面格設定。 若要在狀態之間啟用動畫轉換,會建立動畫控制器資產,並產生預設狀態機器,其中包含相關聯的參數和任何狀態轉換。 狀態機器可以在 Unity 的動畫視窗中檢視。

狀態視覺化檢視和 Unity 動畫系統

狀態視覺化檢視目前會利用 Unity 動畫系統。

按下狀態視覺化檢視中的 [ 產生新動畫剪輯 ] 按鈕時,會根據 Interactive 元素中的狀態名稱產生新的動畫剪輯資產,並放在 MixedRealityToolkit.Generated 資料夾中。 每個狀態容器中的 Animation Clip 屬性都會設定為相關聯的動畫剪輯。

狀態視覺化檢視元件中的動畫剪輯

也會產生 動畫器狀態機器 ,以管理動畫剪輯之間的平滑轉換。 根據預設,狀態機器會利用 [任何狀態 ] 來允許在 Interactive Element 中的任何狀態之間進行轉換。

動畫工具中觸發的狀態視覺化檢視也會針對每個狀態產生,觸發程式參數會用於狀態視覺化檢視來觸發動畫。

Unity 狀態機器

執行階段限制

狀態視覺化檢視必須透過 Inspector 新增至物件,而且無法透過腳本新增。 修改 AnimatorStateMachine/AnimationController 的屬性包含在編輯器命名空間中, (UnityEditor.Animations) 在建置應用程式時移除。

如何使用狀態視覺化檢視

  1. 建立 Cube

  2. 附加互動式元素

  3. 附加狀態視覺化檢視

  4. 選取 [產生新動畫剪輯]

    產生新的動畫剪輯

    在視覺化檢視和互動式元素元件中顯示產生的動畫剪輯

  5. 在 [焦點狀態] 容器中,選取 [ 新增目標]

    新增狀態視覺化檢視目標

  6. 將目前的遊戲物件拖曳至目標欄位

    設定狀態視覺化檢視目標

  7. 開啟 Cube 動畫屬性折迭

  8. 選取 [動畫屬性] 下拉式功能表,然後選取 [色彩]

    設定狀態視覺化檢視色彩

  9. 選取 [新增色彩動畫屬性]

    選取視覺化檢視色彩的動畫屬性

  10. 選擇色彩

    從色彩滾輪選擇視覺化檢視色彩

  11. 按播放並觀察過渡色彩變更

    虛擬手部互動的轉換色彩變更範例

可產生動畫的屬性

動畫屬性的主要用途是簡化動畫剪輯主要畫面格設定。 如果使用者熟悉 Unity 動畫系統,而且偏好直接在產生的動畫剪輯上設定主要畫面格,則他們可以直接將動畫屬性新增至目標物件,並在 Unity 的動畫視窗中開啟剪輯, (Windows > 動畫 > 動畫) 。

如果使用動畫的動畫屬性,曲線類型會設定為 EaseInOut。

目前的可動畫屬性:

刻度位移

Scale Offset Animatable 屬性會採用物件的目前小數位數,並新增定義的位移。

使用虛擬手部互動調整位移

位置位移

Position Offset Animatable 屬性會採用物件的目前位置,並加入定義的位移。

虛擬手部互動的位置位移

色彩

如果材質具有主要色彩屬性,Color Animatable 屬性代表材質的主要色彩。 這個屬性會以動畫顯示 material._Color 屬性。

虛擬手部互動的焦點色彩變更

著色器色彩

著色器色彩動畫屬性是指色彩類型的著色器屬性。 所有著色器屬性都需要屬性名稱。 下列 gif 示範以動畫顯示著色器色彩屬性,Fill_Color不是主要材質色彩。 觀察材質偵測器中的變更值。

虛擬手部互動的著色色彩

著色器浮點數

著色器浮點數動畫屬性是指 float 類型的著色器屬性。 所有著色器屬性都需要屬性名稱。 在下列 gif 中,觀察 Material Inspector for the Material Inspector for the Standard 屬性中的變更值。

具有虛擬手部互動的著色器浮點數

著色器向量

著色器向量動畫屬性是指 Vector4 類型的著色器屬性。 所有著色器屬性都需要屬性名稱。 在下列 gif 中,觀察 Tiling (Main Tex_ST) 屬性之材質偵測器中的變更值。

具有虛擬手部互動的著色器向量

如何尋找可產生動畫效果的著色器屬性名稱

  1. 流覽至視窗 > 動畫 > 動畫

  2. 確定階層中已選取具有狀態視覺化檢視的物件

  3. 在動畫視窗中選取任何動畫剪輯

  4. 選取 [新增屬性],開啟 [網格轉譯器] 折迭

    在動畫視窗中新增動畫屬性

  5. 此清單包含所有 Animatable 屬性名稱的名稱

    動畫視窗中的網格轉譯器動畫屬性

另請參閱