可互動 — MRTK2
元件 Interactable
是一個全容器,可讓任何物件輕鬆 互動 並回應輸入。 Interactionable 可作為所有類型的輸入的攔截功能,包括觸控、手部光線、語音等,以及將這些互動漏斗到 事件 和 視覺主題 回應中。 此元件提供簡單的方法來製作按鈕、變更具有焦點的物件色彩等等。
如何設定 Interactable
此元件允許設定的三個主要區段:
一般輸入設定
狀態
States 是 ScriptableObject 參數,可定義 可互動設定檔 和 視覺主題的互動階段,例如按下或觀察。
DefaultInteractableStates (Assets/MRTK/SDK/Features/UX/Interactable/States/DefaultInteractableStates.asset) 隨附于 MRTK 現用,而且是Interactable元件的預設參數。
DefaultInteractableStates資產包含四種狀態,並利用狀態模型實作 InteractableStates
。
預設值:不會發生任何事,這是最隔離的基底狀態。
焦點:物件正在指向。 這是單一狀態,目前未設定其他狀態,但會排名為 Default。
按下:物件正在指向 ,並按下按鈕或手部。 [按下狀態] 會排名 [預設值] 和 [焦點]。 此狀態也會設定為實體按下的後援。
已停用:按鈕不應該是互動式的,視覺回饋會讓使用者知道此按鈕目前是否無法使用。 理論上,停用狀態可能包含所有其他狀態,但當 Enabled 關閉時,[已停用] 狀態會拒絕所有其他狀態。
位值 (#) 會根據清單中的順序指派給狀態。
注意
建立 Interactiveable 元件時,通常會建議使用 DefaultInteractableStates (Assets/MRTK/SDK/Features/UX/ Interactable /States/DefaultInteractableStates.asset) 。
不過,有 17 個可互動狀態可用來驅動主題,但有些狀態則由其他元件驅動。 以下是內建功能的清單。
- 流覽:已按一下 [互動]。
- 已切換:按鈕處於切換狀態,或維度索引為奇數。
- 手勢:已按下手部或控制器,並已從原始位置移動。
- VoiceCommand:語音命令用來觸發 Interactable。
- PhysicalTouch:目前偵測到觸控輸入,用來
NearInteractionTouchable
啟用。 - 擷取:手部目前正在物件界限中抓取,用來
NearInteractionGrabbable
啟用
Enabled
切換互動是否要啟動。 這會對應至程式 Interactable.IsEnabled
代碼中的 。
Interactable 的enabled 屬性與透過 GameObject/Component (設定的已啟用屬性不同,也就是 SetActive etc) 。 停用 GameObject 或 Interactable MonoBehaviour 將會停用 類別中所有專案,使其無法執行,包括輸入、視覺主題、事件等。透過 停用 Interactable.IsEnabled
會停用大部分的輸入處理、重設相關的輸入狀態。 不過,類別仍會執行每個畫面,並接收將忽略的輸入事件。 這很適合用來以停用狀態顯示可透過視覺主題完成的互動。 一個典型的範例是提交按鈕,等候完成所有必要的輸入欄位。
輸入動作
從互動元件應該回應的輸入組態或控制器對應設定檔中選取輸入動作。
這個屬性可以在執行時間透過 在程式碼 Interactable.InputAction
中設定。
IsGlobal
如果為 true,這會將元件標示為所選 輸入動作的全域輸入接聽程式。 預設行為為 false,將輸入限制為僅此 互動碰撞 器/GameObject。
這個屬性可以在執行時間透過 在程式碼 Interactable.IsGlobal
中設定。
語音命令
語音命令,從 MRTK 語音命令設定檔觸發 OnClick 事件以進行語音互動。
這個屬性可以在執行時間透過 在程式碼 Interactable.VoiceCommand
中設定。
需要焦點
如果為 true,只有當語音命令已從指標取得焦點時,才會啟動 Interactable 。 如果為 false, 則 Interactable 會作為所選語音命令的全域接聽程式。 預設行為為 true,因為多個全域語音接聽程式很難在場景中組織。
這個屬性可以在執行時間透過 在程式碼 Interactable.VoiceRequiresFocus
中設定。
選取模式
這個屬性會定義選取邏輯。 按一下 [互動] 時,它會逐一查看下一個 維度 層級。
維度 類似于排名,並定義輸入以外的狀態 (例如焦點、按下等) 。 它們對於定義切換狀態或其他與按鈕相關聯的多排名狀態很有用。 目前的維度層級是由 Interactable.DimensionIndex
追蹤。
可用的選取模式如下:
- 按鈕 - 維度= 1,簡單可點選的互動
- 切換 - 維度= 2,關閉/ 狀態之間的可互動替代專案
- 多維度 - 尺寸>= 3,每個按一下都會增加目前的維度層級 + 1。 適用于定義清單的按鈕狀態等等。
可互動 也可讓每個 維度定義多個主題。 例如,當 SelectionMode=Toggle時,當取消選取Interactable時,可能會套用一個主題,並在選取元件時套用另一個主題。
目前的選取模式可以透過 Interactable.ButtonMode
在執行時間查詢。 藉由將 屬性設定 Interactable.Dimensions
為符合所需功能,即可在執行時間更新模式。 此外,目前維度對於 切換 和 多維度 模式很有用,可以透過 來 Interactable.CurrentDimension
存取。
可互動的設定檔
設定檔 是建立 GameObject 與 視覺主題之間關聯性的專案。 設定檔會定義當 發生狀態變更時,主題將操作哪些內容。
主題的運作方式非常類似材質。 它們是可編寫腳本的物件,其中包含會根據目前狀態指派給物件的屬性清單。 主題也可重複使用,並可跨多個 Interactable UX 物件指派。
終結時重設
視覺主題會根據選取的主題引擎類別和類型,修改目標 GameObject 上的各種屬性。 如果損毀互動元件時重 設 On Destroy 為 true,則元件會將所有已修改的屬性從使用中主題重設為其原始值。 否則,當終結時,Interactable 元件會保留任何修改的屬性原狀。 在此後者案例中,除非由另一個外部元件改變,否則值的最後狀態將會保存。 預設值為 false。
事件
每個 互動 元件都有一個 OnClick 事件,會在直接選取元件時引發。 不過, Interactable 可用來偵測除了 OnClick以外的輸入事件。
按一下 [ 新增事件 ] 按鈕,以新增類型的事件接收者定義。 新增之後,請選取所需的事件種類。
)
有不同類型的事件接收器可回應不同類型的輸入。 MRTK 隨附下列一組現用接收器。
InteractableAudioReceiver
InteractableOnClickReceiver
InteractableOnFocusReceiver
InteractableOnGrabReceiver
InteractableOnHoldReceiver
InteractableOnPressReceiver
InteractableOnToggleReceiver
InteractableOnTouchReceiver
您可以建立擴充 ReceiverBase
的新類別來建立自訂接收者。
切換事件接收器的範例
可互動的接收者
元件 InteractableReceiver
允許在來源 Interactable 元件之外定義事件。
InteractableReceiver會接聽另一個Interactable所引發的篩選事件種類。 如果未直接指派 Interactable 屬性,則 Search Scope屬性會定義InteractableReceiver在本身、父系或子 GameObject 中接聽事件的方向。
InteractableReceiverList
會以類似的方式運作,但用於比對事件的清單。
建立自訂事件
就像 視覺主題一樣,您可以擴充事件來偵測任何狀態模式或公開功能。
自訂事件可以透過兩種主要方式建立:
ReceiverBase
擴充 類別以建立自訂事件,此事件會顯示在事件種類的下拉式清單中。 依預設會提供 Unity 事件,但可以新增其他 Unity 事件,也可以設定事件來隱藏 Unity 事件。 這項功能可讓設計工具與專案上的工程師合作,以建立設計工具可在編輯器中設定的自訂事件。ReceiverBaseMonoBehavior
擴充 類別,以建立可位於Interactable或其他物件的完全自訂事件元件。ReceiverBaseMonoBehavior
將會參考Interactable來偵測狀態變更。
擴充的範例 ReceiverBase
類別 CustomInteractablesReceiver
會顯示 Interactable 的狀態資訊,以及如何建立自訂事件接收器的範例。
public CustomInteractablesReceiver(UnityEvent ev) : base(ev, "CustomEvent")
{
HideUnityEvents = true; // hides Unity events in the receiver - meant to be code only
}
建立自訂事件接收器時,下列方法有助於覆寫/實作。
ReceiverBase.OnUpdate()
是一種抽象方法,可用來偵測狀態模式/轉換。 此外,當選取[互動]時, ReceiverBase.OnVoiceCommand()
和 ReceiverBase.OnClick()
方法有助於建立自訂事件邏輯。
public override void OnUpdate(InteractableStates state, Interactable source)
{
if (state.CurrentState() != lastState)
{
// the state has changed, do something new
lastState = state.CurrentState();
...
}
}
public virtual void OnVoiceCommand(InteractableStates state, Interactable source,
string command, int index = 0, int length = 1)
{
base.OnVoiceCommand(state, source, command, index, length);
// voice command called, perform some action
}
public virtual void OnClick(InteractableStates state,
Interactable source,
IMixedRealityPointer pointer = null)
{
base.OnClick(state, source);
// click called, perform some action
}
在偵測器中顯示自訂事件接收器欄位
ReceiverBase 腳本會使用 InspectorField
屬性在偵測器中公開自訂屬性。 以下是 Vector3 的範例,這是具有工具提示和標籤資訊的自訂屬性。 選取 Interactable GameObject 且已新增相關聯的 事件接收器 類型時,這個屬性會顯示為可在偵測器中設定。
[InspectorField(Label = "<Property label>",Tooltip = "<Insert tooltip info>",Type = InspectorField.FieldTypes.Vector3)]
public Vector3 EffectOffset = Vector3.zero;
如何使用 Interactable
建置簡單按鈕
您可以將 Interactable 元件新增至設定為接收輸入事件的 GameObject,以建立簡單的按鈕。 它可以有碰撞器或子系上的碰撞器來接收輸入。 如果使用與 Unity UI 型 GameObjects 互動 ,它應該位於 Canvas GameObject 底下。
藉由建立新的設定檔、指派 GameObject 本身和建立新主題,進一步執行按鈕。 此外,使用 OnClick 事件來發生問題。
注意
讓 按鈕可按下 需要 PressableButton
元件。 此外, PhysicalPressEventRouter
漏斗圖按下事件需要元件給 Interactable 元件。
建立切換和多維度按鈕
切換按鈕
若要讓按鈕切換功能,請將 Selection Mode
欄位變更為輸入 Toggle
。 在 [ 設定檔] 區段中,會針對開啟 [互動 ] 時所使用的每個設定檔新增切換的主題。
SelectionMode
當 設定為 [切換] 時,可以使用[IsToggled] 核取方塊,在執行時間初始化時設定控制項的預設值。
CanSelect表示CanDeselect代表反轉時,Interactable可以從開啟到開啟。
開發人員可以使用 SetToggled
和 IsToggled
介面,透過程式碼取得/設定 Interactable 的切換狀態。
// If using SelectionMode = Toggle (i.e Dimensions == 2)
// Make the Interactable selected and toggled on
myInteractable.IsToggled = true;
// Get whether the Interactable is selected or not
bool isSelected = myInteractable.IsToggled;
切換按鈕集合
通常會有一份切換按鈕清單,其中在任何指定時間只能使用一個按鈕,也稱為星形集或選項按鈕等等。
InteractableToggleCollection
使用 元件來啟用這項功能。 此控制項可確保在任何指定時間只切換一個 Interactable 。
RadialSet (Assets/MRTK/SDK/Features/UX/Interactable/Prefabs/RadialSet.prefab) 也是絕佳的起點。
若要建立自訂星形按鈕群組:
- 建立多個 Interactable GameObjects/buttons
- 設定每個 與SelectionMode 互動 = Toggle、 CanSelect = true,以及 CanDeselect = false
- 在所有 Interactables 上建立空的父 GameObject,並新增 InteractableToggleCollection 元件
- 將所有Interactables新增至InteractableToggleCollection上的ToggleList
- 設定 InteractableToggleCollection.CurrentIndex 屬性,以判斷在啟動時預設選取的按鈕
多維度按鈕
多維度選取模式可用來建立循序按鈕,或具有兩個步驟以上的按鈕,例如使用三個值控制速度:快速 (1x) 、快速 (2x) 或最快 (3x) 。
維度是數值時,最多可以新增 9 個主題,以控制每個速度設定按鈕的文字標籤或紋理,每個步驟使用不同的主題。
每次按一下事件都會在執行時間將 前 DimensionIndex
1 往前,直到 Dimensions
達到值為止。 然後迴圈會重設為 0。
開發人員可以評估 , DimensionIndex
以判斷目前作用中的維度。
// If using SelectionMode = Multi-dimension (i.e Dimensions >= 3)
//Access the current DimensionIndex
int currentDimension = myInteractable.CurrentDimension;
//Set the current DimensionIndex to 2
myInteractable.CurrentDimension = 2;
// Promote Dimension to next level
myInteractable.IncreaseDimension();
在執行時間建立 Interactable
您可以在執行時間輕鬆地將可互動新增至任何 GameObject。 下列範例示範如何使用 視覺化主題指派設定檔。
var interactableObject = GameObject.CreatePrimitive(PrimitiveType.Cylinder);
var interactable = interactableObject.AddComponent<Interactable>();
// Get the default configuration for the Theme engine InteractableColorTheme
var newThemeType = ThemeDefinition.GetDefaultThemeDefinition<InteractableColorTheme>().Value;
// Define a color for every state in our Default Interactable States
newThemeType.StateProperties[0].Values = new List<ThemePropertyValue>()
{
new ThemePropertyValue() { Color = Color.black}, // Default
new ThemePropertyValue() { Color = Color.black}, // Focus
new ThemePropertyValue() { Color = Random.ColorHSV()}, // Pressed
new ThemePropertyValue() { Color = Color.black}, // Disabled
};
interactable.Profiles = new List<InteractableProfileItem>()
{
new InteractableProfileItem()
{
Themes = new List<Theme>()
{
Interactable.GetDefaultThemeAsset(new List<ThemeDefinition>() { newThemeType })
},
Target = interactableObject,
},
};
// Force the Interactable to be clicked
interactable.TriggerOnClick()
透過程式碼互動的事件
您可以使用下列範例,透過程式碼將動作新增至基 Interactable.OnClick
底事件。
public static void AddOnClick(Interactable interactable)
{
interactable.OnClick.AddListener(() => Debug.Log("Interactable clicked"));
}
使用 函 Interactable.AddReceiver<T>()
式在執行時間動態新增事件接收器。
下列範例程式碼示範如何新增 InteractableOnFocusReceiver,以接聽焦點進入/結束,並進一步定義在事件實例引發時要執行的動作程式碼。
public static void AddFocusEvents(Interactable interactable)
{
var onFocusReceiver = interactable.AddReceiver<InteractableOnFocusReceiver>();
onFocusReceiver.OnFocusOn.AddListener(() => Debug.Log("Focus on"));
onFocusReceiver.OnFocusOff.AddListener(() => Debug.Log("Focus off"));
}
下列範例程式碼示範如何新增 InteractableOnToggleReceiver,以接聽可切換的 Interactable Interactables上的選取/取消選取狀態轉換,並進一步定義在事件實例引發時要執行的動作程式碼。
public static void AddToggleEvents(Interactable interactable)
{
var toggleReceiver = interactable.AddReceiver<InteractableOnToggleReceiver>();
// Make the interactable have toggle capability, from code.
// In the gui editor it's much easier
interactable.Dimensions = 2;
interactable.CanSelect = true;
interactable.CanDeselect = true;
toggleReceiver.OnSelect.AddListener(() => Debug.Log("Toggle selected"));
toggleReceiver.OnDeselect.AddListener(() => Debug.Log("Toggle un-selected"));
}