可互動 — MRTK2

可互動

元件 Interactable 是一個全容器,可讓任何物件輕鬆 互動 並回應輸入。 Interactionable 可作為所有類型的輸入的攔截功能,包括觸控、手部光線、語音等,以及將這些互動漏斗到 事件視覺主題 回應中。 此元件提供簡單的方法來製作按鈕、變更具有焦點的物件色彩等等。

如何設定 Interactable

此元件允許設定的三個主要區段:

  1. 一般輸入組態
  2. 以多個 GameObject 為目標的視覺主題
  3. 事件處理常式

一般輸入設定

一般可互動設定

狀態

StatesScriptableObject 參數,可定義 可互動設定檔視覺主題的互動階段,例如按下或觀察。

DefaultInteractableStates (Assets/MRTK/SDK/Features/UX/Interactable/States/DefaultInteractableStates.asset) 隨附于 MRTK 現用,而且是Interactable元件的預設參數。

在偵測器中狀態 ScriptableObject 範例

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。

分析ams

事件

每個 互動 元件都有一個 OnClick 事件,會在直接選取元件時引發。 不過, Interactable 可用來偵測除了 OnClick以外的輸入事件。

按一下 [ 新增事件 ] 按鈕,以新增類型的事件接收者定義。 新增之後,請選取所需的事件種類。

事件範例)

有不同類型的事件接收器可回應不同類型的輸入。 MRTK 隨附下列一組現用接收器。

您可以建立擴充 ReceiverBase 的新類別來建立自訂接收者。

事件切換接收器範例

切換事件接收器的範例

可互動的接收者

元件 InteractableReceiver 允許在來源 Interactable 元件之外定義事件。 InteractableReceiver會接聽另一個Interactable所引發的篩選事件種類。 如果未直接指派 Interactable 屬性,則 Search Scope屬性會定義InteractableReceiver在本身、父系或子 GameObject 中接聽事件的方向。

InteractableReceiverList 會以類似的方式運作,但用於比對事件的清單。

可互動的擷取

建立自訂事件

就像 視覺主題一樣,您可以擴充事件來偵測任何狀態模式或公開功能。

自訂事件可以透過兩種主要方式建立:

  1. ReceiverBase擴充 類別以建立自訂事件,此事件會顯示在事件種類的下拉式清單中。 依預設會提供 Unity 事件,但可以新增其他 Unity 事件,也可以設定事件來隱藏 Unity 事件。 這項功能可讓設計工具與專案上的工程師合作,以建立設計工具可在編輯器中設定的自訂事件。

  2. 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可以從開啟開啟

設定檔切換視覺效果主題範例

開發人員可以使用 SetToggledIsToggled 介面,透過程式碼取得/設定 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使用 元件來啟用這項功能。 此控制項可確保在任何指定時間只切換一個 InteractableRadialSet (Assets/MRTK/SDK/Features/UX/Interactable/Prefabs/RadialSet.prefab) 也是絕佳的起點。

若要建立自訂星形按鈕群組:

  1. 建立多個 Interactable GameObjects/buttons
  2. 設定每個 SelectionMode 互動 = Toggle、 CanSelect = true,以及 CanDeselect = false
  3. 在所有 Interactables 上建立空的父 GameObject,並新增 InteractableToggleCollection 元件
  4. 將所有Interactables新增至InteractableToggleCollection上的ToggleList
  5. 設定 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"));
}

另請參閱