Interakcja

Interactable

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:

  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

General Interactable Settings

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.

States ScriptableObject example in inspector

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.

Profile theams

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.

Events example)

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.

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

Event Toggle Receiver Example

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

Interactable reciver

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

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

Profile Toggle Visual Themes Example

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
Toggle collection

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.

Multi-Dimensional profile example

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ż