Interactive 元素 [實驗性] — MRTK2
MRTK 輸入系統的簡化集中式進入點。 包含狀態管理方法、事件管理和核心互動狀態的狀態設定邏輯。
Interactive Element 是 Unity 2019.3 中支援的實驗性功能,其利用 Unity 2019.3 的新功能: 序列化參考。
Interactive 元素偵測器
在播放模式期間,Interactive Element Inspector 會提供視覺化回饋,指出目前狀態是否為作用中。 如果狀態為作用中,則會以青色反白顯示。 如果狀態不是使用中,則色彩不會變更。 偵測器中狀態旁的數位是狀態值,如果狀態為使用中,則值為 1,如果狀態不是作用中,則值為 0。
核心狀態
Interactive Element 包含核心狀態,並支援新增 自訂狀態。 核心狀態是已在 中 BaseInteractiveElement
定義狀態設定邏輯的狀態設定邏輯。 以下是目前輸入驅動核心狀態的清單:
目前的核心狀態
近近與遠互動核心狀態:
近互動核心狀態:
遠距互動核心狀態:
其他核心狀態:
如何透過偵測器新增核心狀態
在 Interactive 元素的偵測器中,流覽至 [ 新增核心狀態 ]。
選取 [ 選取狀態 ] 按鈕,選擇要新增的核心狀態。 功能表中的狀態會依互動類型排序。
開啟 [事件組態] 折迭,以檢視與狀態相關聯的事件和屬性。
如何透過腳本新增核心狀態
AddNewState(stateName)
使用 方法來新增核心狀態。 如需可用核心狀態名稱的清單,請使用 CoreInteractionState
列舉。
// Add by name or add by CoreInteractionState enum to string
interactiveElement.AddNewState("SelectFar");
interactiveElement.AddNewState(CoreInteractionState.SelectFar.ToString());
狀態內部結構
Interactive 元素中的狀態類型為 InteractionState
。
InteractionState
包含下列屬性:
- 名稱:狀態的名稱。
- 值:狀態值。 如果狀態為開啟,狀態值為 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 元素中。
焦點狀態行為
取得焦點狀態事件
焦點狀態的事件組態類型: 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 鍵來觸發。 在語音的編輯器測試中設定概述下列步驟。
如何註冊語音命令/關鍵字
選取 MixedRealityToolkit 遊戲物件
選取 [複製並自訂 目前的設定檔]
流覽至 [輸入] 區段,然後選取 [ 複製 ] 以啟用輸入設定檔的修改
向下捲動至輸入設定檔中的 [語音] 區段,並複製語音設定檔
選取 [新增語音命令]
輸入新的關鍵字。 選擇性:將 KeyCode 變更為 F5 (或其他 KeyCode) ,以允許在編輯器中進行測試。
返回至 Interactive Element Speech 關鍵字狀態偵測器,然後選取 [新增關鍵字]
輸入剛在語音設定檔中註冊的新關鍵字
若要在編輯器中測試語音關鍵字狀態,請按步驟 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 事件。
流覽至在 Interactive 元素的偵測器中 建立自訂狀態 。
輸入新狀態的名稱。 此名稱必須是唯一的,而且不能與現有的核心狀態相同。
選取 [設定狀態名稱 ] 以新增至狀態清單。
這個自訂狀態會使用包含
OnStateOn
和OnStateOff
事件的預設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
下列步驟會逐步解說建立自訂狀態事件組態和接收者檔案的現有範例。
想像一下狀態名稱。 此名稱必須是唯一的,而且不能與現有的核心狀態相同。 為了本範例的目的,狀態名稱將會是 Keyboard。
建立兩個名為 state name + 「Receiver」 和 state name + 「Events」 的 .cs 檔案。 這些檔案的命名會在內部考慮,且必須遵循狀態名稱 + 事件/接收者慣例。
如需檔案內容的詳細資訊,請參閱 KeyboardEvents.cs 和 KeyboardReceiver.cs 檔案。 新的事件組態類別必須繼承自
BaseInteractionEventConfiguration
,而新的事件接收者類別必須繼承自BaseEventReceiver
。 鍵盤狀態的狀態設定範例位於 檔案中CustomStateSettingExample.cs
。使用狀態名稱將狀態新增至 Interactive Element,如果事件組態和事件接收器檔案存在,則會辨識狀態名稱。 自訂事件組態檔中的屬性應該會出現在偵測器中。
如需事件組態和事件接收者檔案的更多範例,請參閱這些路徑中的檔案:
- 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
可壓縮按鈕
此範例場景包含名為 和 CompressableButtonToggle
的 CompressableButton
預製專案,這些預製專案會鏡像使用 Interactive Element 和狀態視覺化檢視所建構的 PressableButtonHoloLens2
按鈕行為。
元件 CompressableButton
目前是 與 BaseInteractiveElement
做為基類的組合 + PressableButton
PressableButtonHoloLens2
。
狀態視覺化檢視 [實驗性]
狀態視覺化檢視元件會根據連結的 Interactive Element 元件中定義的狀態,將動畫新增至物件。 此元件會建立動畫資產、將它們放在 MixedRealityToolkit.Generated 資料夾中,並透過將 Animatable 屬性新增至目標遊戲物件來啟用簡化的動畫主要畫面格設定。 若要在狀態之間啟用動畫轉換,會建立動畫控制器資產,並產生預設狀態機器,其中包含相關聯的參數和任何狀態轉換。 狀態機器可以在 Unity 的動畫視窗中檢視。
狀態視覺化檢視和 Unity 動畫系統
狀態視覺化檢視目前會利用 Unity 動畫系統。
按下狀態視覺化檢視中的 [ 產生新動畫剪輯 ] 按鈕時,會根據 Interactive 元素中的狀態名稱產生新的動畫剪輯資產,並放在 MixedRealityToolkit.Generated 資料夾中。 每個狀態容器中的 Animation Clip 屬性都會設定為相關聯的動畫剪輯。
也會產生 動畫器狀態機器 ,以管理動畫剪輯之間的平滑轉換。 根據預設,狀態機器會利用 [任何狀態 ] 來允許在 Interactive Element 中的任何狀態之間進行轉換。
在動畫工具中觸發的狀態視覺化檢視也會針對每個狀態產生,觸發程式參數會用於狀態視覺化檢視來觸發動畫。
執行階段限制
狀態視覺化檢視必須透過 Inspector 新增至物件,而且無法透過腳本新增。 修改 AnimatorStateMachine/AnimationController 的屬性包含在編輯器命名空間中, (UnityEditor.Animations
) 在建置應用程式時移除。
如何使用狀態視覺化檢視
建立 Cube
附加互動式元素
附加狀態視覺化檢視
選取 [產生新動畫剪輯]
在 [焦點狀態] 容器中,選取 [ 新增目標]
將目前的遊戲物件拖曳至目標欄位
開啟 Cube 動畫屬性折迭
選取 [動畫屬性] 下拉式功能表,然後選取 [色彩]
選取 [新增色彩動畫屬性]
選擇色彩
按播放並觀察過渡色彩變更
可產生動畫的屬性
動畫屬性的主要用途是簡化動畫剪輯主要畫面格設定。 如果使用者熟悉 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) 屬性之材質偵測器中的變更值。
如何尋找可產生動畫效果的著色器屬性名稱
流覽至視窗 > 動畫 > 動畫
確定階層中已選取具有狀態視覺化檢視的物件
在動畫視窗中選取任何動畫剪輯
選取 [新增屬性],開啟 [網格轉譯器] 折迭
此清單包含所有 Animatable 屬性名稱的名稱