Interakcja — MRTK2

Możliwość interakcji

Składnik Interactable jest kontenerem all-in-one, aby każdy obiekt był łatwy do interakcji i odpowiadać 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. te interakcje do zdarzeń i odpowiedzi motywu wizualnego . Ten składnik umożliwia łatwe tworzenie przycisków, zmienianie koloru obiektów fokusem i nie tylko.

Jak skonfigurować interakcję

Składnik umożliwia korzystanie z trzech podstawowych sekcji konfiguracji:

  1. Ogólna konfiguracja danych wejściowych
  2. Motywy wizualne przeznaczone dla wielu obiektów GameObject
  3. Procedury obsługi zdarzeń

Ogólne ustawienia danych wejściowych

Ogólne ustawienia umożliwiające interakcję

Państw

States to parametr ScriptableObject , który definiuje fazy interakcji, takie jak naciśnięcie lub zaobserwowanie, dla profilów z możliwością interakcji i motywów wizualnych.

Element DefaultInteractableStates (Assets/MRTK/SDK/Features/UX/Interactable/States/DefaultInteractableStates.asset) jest dostarczany z wbudowanym zestawem narzędzi MRTK i jest domyślnym parametrem składników, które można wchodzić w interakcję.

Przykład obiektu ScriptableObject w inspektorze

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, obecnie nie ustawiono żadnych innych stanów, ale pozycja Domyślna zostanie ustawiona.

  • Naciśnij: obiekt jest wskazywany na, a naciśnięcie przycisku lub ręki. Pozycja Stan naciśnięcia naciśnięć określa wartość Domyślna i Fokus. Ten stan zostanie również ustawiony jako rezerwowy element fizyczny.

  • Wyłączone: przycisk nie powinien być interakcyjny, a wizualna opinia będzie poinformować użytkownika, czy 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 przewróci 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 elementu DefaultInteractableStates (Assets/MRTK/SDK/Features/UX/Interactable/States/DefaultInteractableStates.asset) podczas tworzenia składników możliwych do interakcji.

Dostępnych jest jednak 17 stanów z możliwością interakcji, których można użyć do obsługi motywów, choć niektóre mają być sterowane przez inne składniki. Oto lista osób z wbudowanymi funkcjami.

  • Odwiedzone: kliknięta została pozycja Interakcja.
  • Przełącznik: przycisk jest w stanie przełączonym lub indeks wymiaru jest liczbą nieparzystkową.
  • Gest: ręka lub kontroler został wciśnięty i przeniesiony z oryginalnej pozycji.
  • VoiceCommand: polecenie mowy zostało użyte do wyzwolenia interakcji.
  • PhysicalTouch: obecnie wykrywane są dane wejściowe dotykowe, których należy użyć NearInteractionTouchable do włączenia.
  • Chwyć: Ręka jest obecnie chwytająca w granicach obiektu, użyj polecenia NearInteractionGrabbable , aby włączyć

Włączono

Przełącza, czy funkcja Interakcji zostanie włączona, czy też 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/Component (np. SetActive itp.). Wyłączenie obiektu GameObject lub Interactable MonoBehaviour spowoduje wyłączenie wszystkich elementów w klasie z uruchamiania, w tym danych wejściowych, motywów wizualnych, zdarzeń itp. Wyłączenie za pośrednictwem spowoduje Interactable.IsEnabled wyłączenie większości obsługi danych wejściowych, resetowanie 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 możliwego do interakcji w stanie wyłączonym, który można wykonać za pomocą motywów wizualnych. Typowym przykładem może być przycisk przesyłania oczekujących na ukończenie wszystkich wymaganych pól wejściowych.

Akcje wejściowe

Wybierz akcję wejściową z profilu mapowania konfiguracji wejściowej lub 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 wartość true, oznacza to składnik jako globalny odbiornik wejściowy dla wybranej akcji wejściowej. Domyślne zachowanie to fałsz, które ogranicza dane wejściowe 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.

Speech Command

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 funkcję Interakcja tylko wtedy, gdy i tylko wtedy, gdy już ma fokus ze wskaźnika. Jeśli wartość false , interakcja będzie działać jako odbiornik globalny dla wybranego polecenia głosowego. Domyślne zachowanie jest prawdziwe, ponieważ wiele odbiorników mowy globalnej może być trudne do zorganizowania 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 przycisku Interakcja następuje iterowanie do następnego poziomu wymiaru . Wymiary są podobne do rangi i definiują stan poza danymi wejściowymi (np. fokus, nacisk itp.). Są one przydatne do definiowania stanów przełącznika lub innych stanów o wielu rangach skojarzonych z przyciskiem. Bieżący poziom wymiaru jest śledzony przez Interactable.DimensionIndexelement .

Dostępne tryby wyboru to:

  • Przycisk - Wymiary = 1, proste kliknięcie z możliwością interakcji
  • Przełącz - Wymiary = 2, możliwość interakcji między stanem wyłączonym/
  • 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 po wybraniu przełącznika SelectionMode=Toggle można zastosować jeden motyw, gdy opcja Interakcja jest zaznaczona, a inny motyw jest stosowany po wybraniu składnika.

Bieżącego trybu wyboru można wykonywać zapytania w czasie wykonywania za pomocą 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 bieżący wymiar, przydatny do przełączania i trybów wielowymiarowych , 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óra będzie manipulowana przez motyw 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 .

Resetuj 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 przy niszczeniu jest prawdziwa, składnik wchodzący w interakcję spowoduje zresetowanie wszystkich zmodyfikowanych 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 wartoś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.

Profilowanie aams

Zdarzenia

Każdy składnik z możliwością interakcji ma zdarzenie OnClick , które jest uruchamiane, gdy składnik jest po prostu wybrany. Można jednak użyć funkcji Interakcji do wykrywania zdarzeń wejściowych innych niż tylko OnClick.

Kliknij przycisk Dodaj zdarzenie , aby dodać nowy typ definicji odbiornika zdarzeń. Po dodaniu wybierz żądany typ zdarzenia.

Przykład zdarzeń)

Istnieją różne typy odbiorników zdarzeń, aby reagować na różne typy danych wejściowych. Zestaw narzędzi MRTK jest dostarczany z następującym zestawem wbudowanych odbiorników.

Niestandardowy odbiornik można utworzyć, tworząc nową klasę, która rozszerza klasę ReceiverBase.

Przykład przełącznika odbiornika zdarzeń

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ń.

Wchodzenie w interakcję — recyt

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:

  1. 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 ustawić je tak, aby ukryć zdarzenia 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.

  2. 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ść.

Przykład przełączania motywów wizualnych profilu

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:

  1. Tworzenie wielu obiektów GameObject/przycisków z możliwością interakcji
  2. Ustaw każdą interakcję z trybem SelectionMode = Toggle, CanSelect = true i CanDeselect = false
  3. Utwórz pusty nadrzędny obiekt GameObject we wszystkich elementach Interakcji i dodaj składnik InteractableToggleCollection
  4. Dodaj wszystkie interakcje do listy toggleList w kolekcji InteractableToggleCollection
  5. Ustaw właściwość InteractableToggleCollection.CurrentIndex , aby określić, który przycisk jest domyślnie zaznaczony przy uruchamianiu
Przełącz kolekcję

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.

Przykład profilu wielowymiarowego

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"));
}

Zobacz też