Interakcja
Składnik Interactable
jest kontenerem all-in-one, aby każdy obiekt był łatwo wchodzić w interakcje i reagować na dane wejściowe. Interakcja działa jako catch-all dla wszystkich typów danych wejściowych, w tym dotyku, promieni rąk, mowy itp. i lejka te interakcje w zdarzeniach i odpowiedziach motywu wizualnego . Ten składnik zapewnia łatwy sposób tworzenia przycisków, zmieniania koloru obiektów z fokusem i nie tylko.
Jak skonfigurować interakcję
Składnik umożliwia korzystanie z trzech podstawowych sekcji konfiguracji:
- Ogólna konfiguracja danych wejściowych
- Motywy wizualne przeznaczone dla wielu obiektów GameObject
- Procedury obsługi zdarzeń
Ogólne ustawienia danych wejściowych
Stany
States to parametr ScriptableObject , który definiuje fazy interakcji, takie jak naciśnięcie lub obserwowanie, dla profilów z możliwością interakcji i motywów wizualnych.
Parametr DefaultInteractableStates (Assets/MRTK/SDK/Features/UX/Interactable/States/DefaultInteractableStates.asset) jest dostarczany z gotowego zestawu NARZĘDZI MRTK i jest domyślnym parametrem dla składników z możliwością interakcji.
Zasób DefaultInteractableStates zawiera cztery stany i wykorzystuje implementację InteractableStates
modelu stanu.
Ustawienie domyślne: Nic się nie dzieje, jest to najbardziej izolowany stan podstawowy.
Fokus: obiekt jest wskazywany. Jest to pojedynczy stan, żadne inne stany nie są obecnie ustawione, ale będzie to pozycja Domyślna.
Naciśnij: obiekt jest wskazywany, a przycisk lub ręka naciska. Stan Naciśnięcie wyprzedaj klasyfikuje wartość Domyślna i Fokus. Ten stan zostanie również ustawiony jako powrót do prasy fizycznej.
Wyłączone: przycisk nie powinien być interaktywny, a opinie wizualne będą powiadamiać użytkownika, jeśli z jakiegoś powodu ten przycisk nie może być w tej chwili używany. Teoretycznie stan wyłączony może zawierać wszystkie inne stany, ale po wyłączeniu opcji Włączone stan Wyłączone przechyli wszystkie inne stany.
Wartość bitowa (#) jest przypisywana do stanu w zależności od kolejności na liście.
Uwaga
Zazwyczaj zaleca się korzystanie z parametru DefaultInteractableStates (Assets/MRTK/SDK/Features/UX/Interactable/States/DefaultInteractableStates.asset) podczas tworzenia składników z możliwością interakcji .
Istnieją jednak 17 stanów, które mogą być używane do obsługi motywów, choć niektóre mają być napędzane przez inne składniki. Oto lista osób z wbudowanymi funkcjami.
- Odwiedzone: kliknięta opcja Interakcja została kliknięta.
- Włączone: przycisk jest w stanie włączonym lub indeks wymiaru jest nieparzystną liczbą.
- Gest: Ręka lub kontroler został naciśnięty i przeniesiony z oryginalnej pozycji.
- VoiceCommand: polecenie mowy zostało użyte do wyzwolenia interakcji.
- PhysicalTouch: dane wejściowe dotykowe są obecnie wykrywane, użyj
NearInteractionTouchable
polecenia w celu włączenia. - Chwyć: Ręka jest obecnie chwytająca w granicach obiektu, użyj
NearInteractionGrabbable
polecenia , aby włączyć
Włączono
Przełącza, czy funkcja Interakcja zostanie włączona, czy nie. Odpowiada to kodowi Interactable.IsEnabled
w kodzie.
Właściwość włączona w interakcję różni się od właściwości włączonej skonfigurowanej za pośrednictwem obiektu GameObject/Składnika (tj. SetActive itp.). Wyłączenie obiektu GameObject lub Interakcja MonoBehaviour spowoduje wyłączenie wszystkich elementów w klasie, w tym danych wejściowych, motywów wizualnych, zdarzeń itp. Wyłączenie za pośrednictwem Interactable.IsEnabled
spowoduje wyłączenie większości obsługi danych wejściowych, zresetowanie powiązanych stanów wejściowych. Jednak klasa będzie nadal uruchamiać każdą ramkę i odbierać zdarzenia wejściowe, które zostaną zignorowane. Jest to przydatne w przypadku wyświetlania funkcji Interakcji w stanie wyłączonym, które można wykonać za pomocą motywów wizualnych. Typowym przykładem tego jest przycisk przesyłania oczekującego na ukończenie wszystkich wymaganych pól wejściowych.
Akcje wejściowe
Wybierz akcję wejściową z profilu konfiguracji wejściowej lub mapowania kontrolera, na który powinien reagować składnik Interakcja .
Tę właściwość można skonfigurować w czasie wykonywania w kodzie za pomocą polecenia Interactable.InputAction
.
IsGlobal
Jeśli to prawda, będzie to oznaczać składnik jako odbiornik danych wejściowych globalnych dla wybranej akcji wejściowej. Domyślne zachowanie jest fałszywe, co spowoduje ograniczenie danych wejściowych tylko do tego kolidera z możliwością interakcji /obiektu GameObject.
Tę właściwość można skonfigurować w czasie wykonywania w kodzie za pomocą polecenia Interactable.IsGlobal
.
Polecenie mowy
Polecenie mowy z profilu poleceń mowy zestawu narzędzi MRTK w celu wyzwolenia zdarzenia OnClick na potrzeby interakcji głosowej.
Tę właściwość można skonfigurować w czasie wykonywania w kodzie za pomocą polecenia Interactable.VoiceCommand
.
Wymaga fokusu
Jeśli to prawda, polecenie głosowe aktywuje tylko możliwość interakcji , jeśli i tylko wtedy, gdy ma już fokus z wskaźnika. Jeśli wartość false, funkcja Interakcja będzie działać jako odbiornik globalny dla wybranego polecenia głosowego. Domyślne zachowanie jest prawdziwe, ponieważ wiele globalnych odbiorników mowy może być trudne do organizowania w scenie.
Tę właściwość można skonfigurować w czasie wykonywania w kodzie za pomocą polecenia Interactable.VoiceRequiresFocus
.
Tryb zaznaczenia
Ta właściwość definiuje logikę wyboru. Po kliknięciu pozycji Interakcja iteruje go do następnego poziomu wymiaru . Wymiary są podobne do rangi i definiują stan poza danymi wejściowymi (np. fokus, naciśnięcie itp.). Są one przydatne do definiowania stanów przełącznika lub innych stanów wielo rangi skojarzonych z przyciskiem. Bieżący poziom wymiaru jest śledzony przez element Interactable.DimensionIndex
.
Dostępne tryby wyboru to:
- Przycisk - Wymiary = 1, łatwo dostępne do interakcji
- Przełącz - Wymiary = 2, możliwe do interakcji alternatywne między stanem/wyłączenia
- Wiele wymiarów - Wymiary> = 3, każde kliknięcie zwiększa bieżący poziom wymiaru + 1. Przydatne do definiowania stanu przycisku na liście itp.
Możliwość interakcji umożliwia również zdefiniowanie wielu motywów na wymiar. Na przykład gdy przełącznik SelectionMode=Toggle można zastosować jeden motyw, gdy opcja Interakcja jest zaznaczona , a inny motyw zastosowany po wybraniu składnika.
Bieżący tryb zaznaczenia można wykonywać zapytania w czasie wykonywania za pośrednictwem polecenia Interactable.ButtonMode
. Aktualizowanie trybu w czasie wykonywania można osiągnąć, ustawiając Interactable.Dimensions
właściwość tak, aby odpowiadała żądanej funkcjonalności. Ponadto dostęp do bieżącego wymiaru, przydatnego w trybach przełączania i wielowymiarowego , można uzyskać dostęp za pośrednictwem polecenia Interactable.CurrentDimension
.
Profile z możliwością interakcji
Profile to elementy, które tworzą relację między obiektem GameObject i motywem wizualnym. Profil definiuje zawartość, którą będzie manipulować motywem po zmianie stanu.
Motywy działają bardzo podobnie jak materiały. Są to obiekty skryptowe zawierające listę właściwości, które zostaną przypisane do obiektu na podstawie bieżącego stanu. Motywy są również wielokrotnego użytku i można je przypisać w wielu obiektach środowiska użytkownika z możliwością interakcji .
Resetowanie przy niszczeniu
Motywy wizualne modyfikują różne właściwości obiektu GameObject, zależne od wybranej klasy i typu aparatu motywu. Jeśli wartość Resetuj na niszczeniu jest prawdziwa, gdy składnik Interakcja zostanie zniszczony, składnik zresetuje wszystkie zmodyfikowane właściwości z aktywnych motywów do ich oryginalnych wartości. W przeciwnym razie, gdy zostanie zniszczony, składnik z możliwością interakcji pozostawi wszelkie zmodyfikowane właściwości zgodnie z rzeczywistymi właściwościami. W tym ostatnim przypadku ostatni stan wartości będzie się powtarzać, chyba że zostanie zmieniony przez inny składnik zewnętrzny. Wartością domyślną jest false.

Zdarzenia
Każdy składnik z możliwością interakcji ma zdarzenie OnClick , które jest uruchamiane, gdy składnik jest po prostu wybrany. Jednak interakcja może służyć do wykrywania zdarzeń wejściowych innych niż tylko OnClick.
Kliknij przycisk Dodaj zdarzenie , aby dodać nowy typ definicji odbiorcy zdarzeń. Po dodaniu wybierz żądany typ zdarzenia.
)
Istnieją różne typy odbiorników zdarzeń, które reagują na różne typy danych wejściowych. Zestaw MRTK jest dostarczany z następującym zestawem odbiorników gotowe do użycia.
InteractableAudioReceiver
InteractableOnClickReceiver
InteractableOnFocusReceiver
InteractableOnGrabReceiver
InteractableOnHoldReceiver
InteractableOnPressReceiver
InteractableOnToggleReceiver
InteractableOnTouchReceiver
Niestandardowy odbiornik można utworzyć, tworząc nową klasę, która rozszerza ReceiverBase
klasę .
Przykład odbiornika zdarzeń przełączania
Odbiorniki z możliwością interakcji
Składnik InteractableReceiver
umożliwia definiowanie zdarzeń poza źródłowym składnikiem z możliwością interakcji . Element InteractableReceiver nasłuchuje filtrowanego typu zdarzenia wyzwolonego przez inną interakcję. Jeśli właściwość Interakcja nie jest przypisana bezpośrednio, właściwość Zakres wyszukiwania definiuje kierunek, w którym element InteractableReceiver nasłuchuje zdarzeń, które są na siebie, w obiekcie nadrzędnym lub w podrzędnym obiekcie GameObject.
InteractableReceiverList
działa w podobny sposób, ale dla listy pasujących zdarzeń.

Tworzenie zdarzeń niestandardowych
Podobnie jak motywy wizualne, zdarzenia można rozszerzyć, aby wykrywać dowolny wzorzec stanu lub uwidaczniać funkcje.
Zdarzenia niestandardowe można tworzyć na dwa główne sposoby:
Rozszerz klasę,
ReceiverBase
aby utworzyć zdarzenie niestandardowe, które będzie wyświetlane na liście rozwijanej typów zdarzeń. Domyślnie udostępniane jest zdarzenie aparatu Unity, ale można dodać dodatkowe zdarzenia aparatu Unity lub można ustawić to zdarzenie w celu ukrycia zdarzeń aparatu Unity. Ta funkcja umożliwia projektantowi pracę z inżynierem nad projektem w celu utworzenia niestandardowego zdarzenia, które projektant może skonfigurować w edytorze.Rozszerz klasę w
ReceiverBaseMonoBehavior
celu utworzenia całkowicie niestandardowego składnika zdarzeń, który może znajdować się w wchodzić w interakcję lub innym obiekcie. Element będzie odwoływać się do funkcji InterakcjaReceiverBaseMonoBehavior
w celu wykrywania zmian stanu.
Przykład rozszerzania ReceiverBase
Klasa CustomInteractablesReceiver
wyświetla informacje o stanie interakcji i jest przykładem sposobu tworzenia niestandardowego odbiornika zdarzeń.
public CustomInteractablesReceiver(UnityEvent ev) : base(ev, "CustomEvent")
{
HideUnityEvents = true; // hides Unity events in the receiver - meant to be code only
}
Poniższe metody są przydatne do zastępowania/implementowania podczas tworzenia niestandardowego odbiornika zdarzeń. ReceiverBase.OnUpdate()
jest abstrakcyjną metodą, która może służyć do wykrywania wzorców/przejść stanu. Ponadto ReceiverBase.OnVoiceCommand()
metody i ReceiverBase.OnClick()
są przydatne do tworzenia niestandardowej logiki zdarzeń po wybraniu opcji Interakcja .
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
}
Wyświetlanie niestandardowych pól odbiornika zdarzeń w inspektorze
Skrypty ReceiverBase używają InspectorField
atrybutów do uwidaczniania właściwości niestandardowych w inspektorze. Oto przykład vector3, właściwość niestandardowa z etykietką narzędzia i informacjami o etykiecie. Ta właściwość będzie wyświetlana jako konfigurowalna w inspektorze po wybraniu obiektu GameObject z możliwością interakcji i dodaniu skojarzonego typu odbiornika zdarzeń .
[InspectorField(Label = "<Property label>",Tooltip = "<Insert tooltip info>",Type = InspectorField.FieldTypes.Vector3)]
public Vector3 EffectOffset = Vector3.zero;
Jak korzystać z możliwości interakcji
Tworzenie prostego przycisku
Można utworzyć prosty przycisk, dodając składnik Interakcja do obiektu GameObject skonfigurowanego do odbierania zdarzeń wejściowych. Może mieć na nim zderzacz lub element podrzędny do odbierania danych wejściowych. Jeśli używasz funkcji Interakcji z obiektami GameObject opartymi na interfejsie użytkownika aparatu Unity, powinna znajdować się w obszarze Canvas GameObject.
Wykonaj ten przycisk o krok dalej, tworząc nowy profil, przypisując sam obiekt GameObject i tworząc nowy motyw. Ponadto użyj zdarzenia OnClick , aby coś się stało.
Uwaga
Naciśnięcie przycisku wymaga PressableButton
składnika. Ponadto składnik jest potrzebny do lejkowego PhysicalPressEventRouter
naciśnięcia zdarzeń do składnika z możliwością interakcji .
Tworzenie przycisków przełącznika i wielowymiarowych
Przycisk przełączania
Aby włączyć przełącznik przycisku, zmień pole na Selection Mode
.Toggle
W sekcji Profile dla każdego profilu jest dodawany nowy motyw z włączonym przełączaniem.
SelectionMode
Gdy parametr jest ustawiony na przełącznik, można użyć pola wyboru IsToggled, aby ustawić wartość domyślną kontrolki podczas inicjowania środowiska uruchomieniowego.
CanSelect oznacza, że interakcja może przechodzić od wyłączonego do włączonego , podczas gdy funkcja CanDeselect oznacza odwrotność.
Deweloperzy mogą używać SetToggled
interfejsów i IsToggled
do pobierania/ustawiania stanu przełącznika elementu Możliwe do interakcji za pomocą kodu.
// 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;
Przełącz kolekcję przycisków
Często istnieje lista przycisków przełącznika, w których tylko jeden może być aktywny w danym momencie, znany również jako zestaw promieniowy lub przyciski radiowe itp.
Użyj składnika , InteractableToggleCollection
aby włączyć tę funkcję. Ta kontrolka zapewnia, że w danym momencie włączono tylko jedną interakcję . Pakiet RadialSet (Assets/MRTK/SDK/Features/UX/Interactable/Prefabs/RadialSet.prefab) jest również doskonałym punktem wyjścia.
Aby utworzyć niestandardową grupę przycisków promieniowych:
- Tworzenie wielu obiektów GameObject/przycisków z możliwością interakcji
- Ustaw każdą interakcję z trybem SelectionMode = Toggle, CanSelect = true i CanDeselect = false
- Utwórz pusty nadrzędny obiekt GameObject we wszystkich elementach Interakcji i dodaj składnik InteractableToggleCollection
- Dodaj wszystkie interakcje do listy toggleList w kolekcji InteractableToggleCollection
- Ustaw właściwość InteractableToggleCollection.CurrentIndex , aby określić, który przycisk jest domyślnie zaznaczony przy uruchamianiu

Przycisk wielowymiarowy
Tryb wyboru wielowymiarowego służy do tworzenia przycisków sekwencyjnych lub przycisku, który ma więcej niż dwa kroki, takie jak sterowanie szybkością z trzema wartościami, Szybkie (1x), Szybsze (2x) lub Najszybsze (3x).
W przypadku wymiarów będących wartością liczbową można dodać do 9 motywów, aby kontrolować etykietę tekstową lub teksturę przycisku dla każdego ustawienia szybkości, używając innego motywu dla każdego kroku.
Każde zdarzenie kliknięcia będzie przechodzić DimensionIndex
przez 1 w czasie wykonywania do momentu Dimensions
osiągnięcia wartości. Następnie cykl zostanie zresetowany do 0.
Deweloperzy mogą ocenić element , DimensionIndex
aby określić, który wymiar jest obecnie aktywny.
// 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();
Tworzenie z możliwością interakcji w czasie wykonywania
Możliwość interakcji można łatwo dodać do dowolnego obiektu GameObject w czasie wykonywania. W poniższym przykładzie pokazano, jak przypisać profil z motywem wizualnym.
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()
Zdarzenia z możliwością interakcji za pośrednictwem kodu
Można dodać akcję do zdarzenia podstawowego Interactable.OnClick
za pomocą kodu z poniższym przykładem.
public static void AddOnClick(Interactable interactable)
{
interactable.OnClick.AddListener(() => Debug.Log("Interactable clicked"));
}
Interactable.AddReceiver<T>()
Użyj funkcji , aby dynamicznie dodawać odbiorniki zdarzeń w czasie wykonywania.
W poniższym przykładowym kodzie pokazano, jak dodać element InteractableOnFocusReceiver, który nasłuchuje fokusu enter/exit, a ponadto zdefiniuj kod akcji do wykonania podczas uruchamiania wystąpień zdarzenia.
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"));
}
W poniższym przykładowym kodzie pokazano, jak dodać element InteractableOnToggleReceiver, który nasłuchuje wybranych/niezaznaczonego przejścia stanu w przełącznikach, a ponadto definiuje kod akcji do wykonania, gdy wystąpienia zdarzenia są uruchamiane.
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"));
}