Wskaźniki — MRTK2

Wskaźnik

W tym artykule opisano sposób konfigurowania danych wejściowych wskaźnika i reagowania na nie w praktyce. Aby lepiej zrozumieć, jak kontrolować wiele wskaźników na wysokim poziomie, zobacz Architektura wskaźnika.

Wskaźniki są tworzone automatycznie w czasie wykonywania po wykryciu nowego kontrolera. Do kontrolera można dołączyć więcej niż jeden wskaźnik. Na przykład z domyślnym profilem wskaźnika kontrolery Windows Mixed Reality uzyskać zarówno linię, jak i wskaźnik paraboliczny dla normalnego wyboru i teleportacji odpowiednio.

Konfiguracja wskaźnika

Wskaźniki są konfigurowane jako część systemu wejściowego w zestawie narzędzi MRTK za pośrednictwem elementu MixedRealityPointerProfile. Ten typ profilu jest przypisywany do MixedRealityInputSystemProfile obiektu w inspektorze konfiguracji zestawu narzędzi MRTK. Profil wskaźnika określa kursor, typy wskaźników dostępnych w czasie wykonywania oraz sposób komunikowania się tych wskaźników ze sobą w celu określenia, który z nich jest aktywny.

  • Zakres wskazujący — definiuje maksymalną odległość, dla której wskaźnik może wchodzić w interakcję z obiektem GameObject.

  • Wskazywanie masek warstw Raycast — jest to priorytetowa tablica Maski warstw, aby określić, z którymi elementami GameObjects każda dana kontrolka może wchodzić w interakcje, oraz kolejność interakcji. Może to być przydatne, aby zapewnić interakcję wskaźników z elementami interfejsu użytkownika przed innymi obiektami sceny. Przykład profilu wskaźnika

Konfiguracja opcji wskaźnika

Domyślna konfiguracja profilu wskaźnika MRTK obejmuje następujące klasy wskaźników i skojarzone prefabrykaty gotowe do użycia. Lista wskaźników dostępnych dla systemu w czasie wykonywania jest definiowana w obszarze Opcje wskaźnika w profilu wskaźnika. Deweloperzy mogą używać tej listy do ponownego konfigurowania istniejących wskaźników, dodawania nowych wskaźników lub usuwania.

Przykład profilu opcji wskaźnika

Każdy wpis wskaźnika jest definiowany przez następujący zestaw danych:

  • Typ kontrolera — zestaw kontrolerów, dla których wskaźnik jest prawidłowy.

    • Na przykład pokePointer jest odpowiedzialny za "wyłuskanie" obiektów palcem i jest domyślnie oznaczone jako obsługujące tylko typ kontrolera ręki artykułowanej. Wskaźniki są tworzone tylko wtedy, gdy kontroler stanie się dostępny, a w szczególności typ kontrolera określa, z jakimi kontrolerami można utworzyć prefabrykat tego wskaźnika.
  • Rękojmia — umożliwia utworzenie wystąpienia wskaźnika tylko dla określonej ręki (po lewej/prawej)

Uwaga

Ustawienie właściwości Wręczenie wpisu wskaźnika na None spowoduje skuteczne wyłączenie go z systemu jako alternatywy dla usunięcia tego wskaźnika z listy.

  • Prefab wskaźnika — ten zasób przedfabowy zostanie utworzony po rozpoczęciu śledzenia kontrolera zgodnego z określonym typem kontrolera i przekazaniem.

Istnieje możliwość posiadania wielu wskaźników skojarzonych z kontrolerem. Na przykład w elemencie DefaultHoloLens2InputSystemProfile (Assets/MRTK/SDK/Profiles/HoloLens2/) przegubowy kontroler dłoni jest skojarzony z pokePointer, GrabPointer i DefaultControllerPointer (tj. promienie dłoni).

Uwaga

Zestaw narzędzi MRTK udostępnia zestaw prefabów wskaźnika w elementach Assets/MRTK/SDK/Features/UX/Prefabs/Pointers. Nowy niestandardowy prefab można skompilować tak długo, jak zawiera jeden ze skryptów wskaźnika w Assets/MRTK/SDK/Features/UX/Scripts/Pointers lub dowolny inny skrypt implementujący IMixedRealityPointer.

Konfiguracja kursora

Kursor spojrzenia można skonfigurować bezpośrednio za pośrednictwem GazeCursorPrefab właściwości w MixedRealityInputSystemProfile edytorze. Aby skonfigurować kursor używany dla innych wskaźników, należy zmienić prefab używany w CursorPrefab polu odpowiedniego BaseControllerPointerelementu . Aby zmienić kursor programowo, zmodyfikuj BaseCursor właściwość odpowiedniego IMixedRealityPointer zachowania.

Właściwość prefab kursora

Zobacz nasze prefabryki kursorów w temacie Assets/MRTK/SDK/Features/UX/Prefabs/Cursors , na przykład implementacje zachowania kursora. W szczególności element DefaultGazeCursor zapewnia niezawodną implementację zmiany grafiki kursora na podstawie stanu kontekstowego.

Domyślne klasy wskaźników

Poniższe klasy to gotowe wskaźniki MRTK dostępne i zdefiniowane w domyślnym profilu wskaźnika MRTK opisane powyżej. Każda prefab wskaźnika podana w obszarze Assets/MRTK/SDK/Features/UX/Prefabs/Pointers zawiera jeden z dołączonych składników wskaźnika.

Domyślne wskaźniki zestawu narzędzi MRTK

Skrajne wskaźniki

LinePointer

LinePointer, klasa wskaźnika podstawowego, rysuje linię ze źródła danych wejściowych (tj. kontrolera) w kierunku wskaźnika i obsługuje pojedyncze rzutowanie promienia w tym kierunku. Ogólnie rzecz biorąc, klasy podrzędne, takie jak wskaźniki teleportu ShellHandRayPointer i teleportu, są tworzone i używane (które również rysują linie, aby wskazać, gdzie teleportacja skończy się na) zamiast tej klasy, która zapewnia głównie typowe funkcje.

W przypadku kontrolerów ruchu, takich jak Oculus, Vive i Windows Mixed Reality, obrót będzie zgodny z rotacją kontrolera. W przypadku innych kontrolerów, takich jak HoloLens 2 przegubowych rąk, rotacja jest zgodna z podaną przez system postawą wskazującą rękę.

Linia wskaźnika MRTK
CurvePointer

CurvePointer rozszerza klasę LinePointer , umożliwiając rzutowanie promieni wieloetapowych wzdłuż krzywej. Ta klasa wskaźnika podstawowego jest przydatna w przypadku wystąpień zakrzywionych, takich jak wskaźniki teleportacji, w których linia konsekwentnie zgina się do paraboli.

ShellHandRayPointer

Implementacja shellHandRayPointer, która rozciąga się od LinePointer, jest używana jako domyślna dla profilu wskaźnika MRTK. Prefab DefaultControllerPointer implementuje klasę ShellHandRayPointer .

GGVPointer

Znany również jako wskaźnik Gaze/Gest/Voice (GGV), GGVPointer obsługuje interakcję w stylu HoloLens 1 i naciśnij, przede wszystkim za pośrednictwem funkcji Gaze and Air Tap lub Spojrzenie i głos Wybierz interakcję. Położenie i kierunek wskaźnika GGV są sterowane pozycją i rotacją głowy.

TouchPointer

Funkcja TouchPointer jest odpowiedzialna za pracę z wejściem aparatu Unity Touch (tj. ekran dotykowy). Są to "dalekie interakcje", ponieważ akt dotykania ekranu będzie rzutować ray z kamery do potencjalnie dalekiej lokalizacji na scenie.

MousePointer

MousePointer zasila ekran world raycast na dalekie interakcje, ale dla myszy zamiast dotyku.

Wskaźnik myszy

Uwaga

Obsługa myszy nie jest domyślnie dostępna w zestawie narzędzi MRTK, ale może być włączona przez dodanie nowego dostawcy danych wejściowychMouseDeviceManager typu do profilu wejściowego zestawu NARZĘDZI MRTK i przypisanie MixedRealityMouseInputProfile go do dostawcy danych.

W pobliżu wskaźników

PokePointer

PokePointer służy do interakcji z obiektami gry, które obsługują "niemal interakcję touchable". które są obiektami GameObject, które mają dołączony NearInteractionTouchable skrypt. W przypadku aparatu UnityUI ten wskaźnik szuka parametru NearInteractionTouchableUnityUIs. Program PokePointer używa funkcji SphereCast do określania najbliższego elementu dotykowego i służy do zasilania elementów takich jak przyciski z możliwością naciśnięcia.

Podczas konfigurowania obiektu GameObject przy użyciu NearInteractionTouchable składnika należy skonfigurować parametr localForward , aby wskazać z przodu przycisku lub innego obiektu, który powinien być dotykowy. Upewnij się również, że granice touchable są zgodne z granicami obiektu touchable.

Przydatne właściwości wskaźnika poke:

  • TouchableDistance: Maksymalna odległość, w której można wchodzić w interakcję z powierzchnią dotykową
  • Wizualizacje: obiekt gry używany do renderowania wizualizacji palca (domyślnie pierścień na palcach).
  • Linia: Opcjonalny wiersz do rysowania z palca do aktywnej powierzchni wejściowej.
  • Maski warstw poke — priorytetowa tablica Maski warstw w celu określenia, z którymi elementami GameObject może korzystać wskaźnik, oraz kolejność interakcji. Należy pamiętać, że element GameObject musi również mieć NearInteractionTouchable składnik w celu interakcji ze wskaźnikiem poke.
Wskaźnik poke
SpherePointer

Obiekt SpherePointer używa aparatu UnityEngine.Physics.OverlapSphere w celu zidentyfikowania najbliższego NearInteractionGrabbable obiektu do interakcji, co jest przydatne w przypadku danych wejściowych "chwytalnych", takich jak ManipulationHandler. Podobnie jak w przypadku pary funkcjonalnejPokePointer/NearInteractionTouchable, aby można było wchodzić w interakcje ze wskaźnikiem sphere, obiekt gry musi zawierać składnik, który jest skryptem.NearInteractionGrabbable

Chwyć wskaźnik

Przydatne właściwości wskaźnika sphere:

  • Promień rzutowania sfery: promień dla sfery używanej do wykonywania zapytań dotyczących obiektów, które można przechwycić.
  • Blisko marginesu obiektu: odległość w górnej części promienia rzutowania sfery na zapytanie dotyczące wykrywania, czy obiekt znajduje się w pobliżu wskaźnika. Total Near Object detection radius is Sphere Cast Radius + Near Object Margin
  • Kąt w pobliżu sektora obiektów: kąt wokół osi przodu wskaźnika do wykonywania zapytań dotyczących pobliskich obiektów. Sprawia, że funkcja zapytania jest podobna IsNearObject do stożka. Jest to domyślnie ustawione na 66 stopni, aby dopasować zachowanie urządzenia Hololens 2

Wskaźnik sfery zmodyfikowany do zapytania tylko dla obiektów w kierunku do przodu

  • Współczynnik smoothingu obiektu bliskiego obiektu: współczynnik wygładzeń do wykrywania obiektów bliskich. Jeśli obiekt zostanie wykryty w promie obiektu bliskiego, zapytany promień staje się w pobliżu promień obiektu * (1 + Współczynnik smoothing obiektu bliskiego) w celu zmniejszenia poufności i utrudnić obiektowi pozostawienie zakresu wykrywania.
  • Chwytaj maski warstw — priorytetowa tablica Maski warstw, aby określić, z którymi elementami GameObject może korzystać wskaźnik, oraz kolejność interakcji. Należy pamiętać, że obiekt GameObject musi mieć również element NearInteractionGrabbable do interakcji z usługą SpherePointer.

    Uwaga

    Warstwa rozpoznawania przestrzennego jest wyłączona w domyślnym prefabcie narzędzia GrabPointer dostarczonym przez zestaw narzędzi MRTK. Ma to na celu zmniejszenie wpływu na wydajność wykonywania zapytań nakładających się na sferę za pomocą siatki przestrzennej. Można to włączyć, modyfikując prefab programu GrabPointer.

  • Ignoruj zderzacze Nie w FOV — czy ignorować zderzacze, które mogą być w pobliżu wskaźnika, ale nie w rzeczywistości w wizualizacji FOV. Może to zapobiec przypadkowym chwytom i pozwoli na włączenie promieni dłoni, gdy może być w pobliżu chwytanego, ale nie może go zobaczyć. Wizualizacja FOV jest definiowana za pośrednictwem stożka zamiast typowej frustum ze względów wydajności. Ten stożek jest wyśrodkowany i zorientowany tak samo jak frustum aparatu z promieniem równym pół wysokości wyświetlacza (lub pionoweJ FOV).
Wskaźnik sfery

Wskaźniki teleportu

  • TeleportPointer program zgłosi żądanie teleportu po podjęciu akcji (tj. naciśnięciu przycisku teleportu) w celu przeniesienia użytkownika.
  • ParabolicTeleportPointer program zgłosi żądanie teleportu po podjęciu akcji (tj. naciśnięciu przycisku teleportu) z promieniem linii parabolicznej w celu przeniesienia użytkownika.
Wskaźnik Paraboliczny

Obsługa wskaźnika dla platform rzeczywistości mieszanej

W poniższej tabeli przedstawiono typy wskaźników, które są zwykle używane dla typowych platform w zestawie narzędzi MRTK. UWAGA: istnieje możliwość dodania różnych typów wskaźników do tych platform. Można na przykład dodać wskaźnik Poke lub wskaźnik Sphere do vr. Ponadto urządzenia VR z gamepadem mogą używać wskaźnika GGV.

Wskaźnik OpenVR Windows Mixed Reality HoloLens 1 HoloLens 2
ShellHandRayPointer Prawidłowe Prawidłowe Prawidłowe
TeleportPointer Prawidłowe Prawidłowe
GGVPointer Prawidłowe
SpherePointer Prawidłowe
PokePointer Prawidłowe

Interakcje wskaźnika za pomocą kodu

Interfejsy zdarzeń wskaźnika

MonoBehaviours, które implementują co najmniej jeden z następujących interfejsów i są przypisane do obiektu GameObject z elementem Collider , będą odbierać zdarzenia interakcji wskaźnika zdefiniowane przez skojarzony interfejs.

Zdarzenie Opis Program obsługi
Przed zmianą fokusu/zmianą fokusu Podniesione zarówno na obiekt gry traci fokus, jak i ten, który zyskuje za każdym razem, gdy wskaźnik zmienia fokus. IMixedRealityFocusChangedHandler
Klawisz Focus Enter/Exit Podniesione na obiekt gry zyskuje fokus, gdy pierwszy wskaźnik wchodzi do niego i na tym, który traci fokus, gdy ostatni wskaźnik pozostawia go. IMixedRealityFocusHandler
Wskaźnik w dół / przeciągnięty / w górę / kliknięto Podniesiono do naciśnięcia wskaźnika raportu, przeciągnij i zwolnij. IMixedRealityPointerHandler
Rozpoczęto dotyk / zaktualizowano / ukończono Podniesione przez wskaźniki obsługujące dotyk, takie jak PokePointer zgłaszanie aktywności dotykowej. IMixedRealityTouchHandler

Uwaga

IMixedRealityFocusChangedHandler i IMixedRealityFocusHandler powinny być obsługiwane w obiektach, na których są wywoływane. Istnieje możliwość globalnego odbierania zdarzeń fokusu, ale w przeciwieństwie do innych zdarzeń wejściowych, globalna procedura obsługi zdarzeń nie będzie blokować odbierania zdarzeń na podstawie fokusu (zdarzenie zostanie odebrane zarówno przez program obsługi globalnej, jak i odpowiedni obiekt w fokusie).

Zdarzenia wejściowe wskaźnika w akcji

Zdarzenia wejściowe wskaźnika są rozpoznawane i obsługiwane przez system wejściowy MRTK w podobny sposób jak zwykłe zdarzenia wejściowe. Różnica jest taka, że zdarzenia wejściowe wskaźnika są obsługiwane tylko przez obiekt GameObject w fokusie przez wskaźnik, który wystrzelił zdarzenie wejściowe, a także wszelkie globalne procedury obsługi danych wejściowych. Regularne zdarzenia wejściowe są obsługiwane przez obiekty GameObject w fokusie dla wszystkich aktywnych wskaźników.

  1. System wejściowy MRTK rozpoznaje zdarzenie wejściowe wystąpiło
  2. System wejściowy MRTK uruchamia odpowiednią funkcję interfejsu dla zdarzenia wejściowego dla wszystkich zarejestrowanych globalnych procedur obsługi danych wejściowych
  3. System wejściowy określa, który obiekt GameObject znajduje się w fokusie dla wskaźnika, który wystrzelił zdarzenie
    1. System danych wejściowych korzysta z systemu zdarzeń aparatu Unity , aby uruchomić odpowiednią funkcję interfejsu dla wszystkich pasujących składników w skoncentrowanym obiekcie GameObject
    2. Jeśli w jakimkolwiek momencie zdarzenie wejściowe zostało oznaczone jako używane, proces zakończy się, a żadne dalsze obiekty GameObjects nie otrzymają wywołań zwrotnych.
      • Przykład: Składniki implementowane interfejsu IMixedRealityFocusHandler będą wyszukiwane pod kątem zysków lub utraty fokusu obiektu GameObject
      • Uwaga: System zdarzeń aparatu Unity będzie bąbelkować w celu wyszukania nadrzędnego obiektu GameObject, jeśli w bieżącym obiekcie GameObject nie znaleziono żadnych składników pasujących do żądanego interfejsu.
  4. Jeśli żadne globalne programy obsługi danych wejściowych nie są zarejestrowane i nie znaleziono obiektu GameObject z pasującym składnikiem/interfejsem, system wejściowy będzie wywoływać każdy rezerwowy zarejestrowanych programów obsługi danych wejściowych

Przykład

Poniżej znajduje się przykładowy skrypt, który zmienia kolor dołączonego modułu renderowania, gdy wskaźnik przyjmuje fokus lub opuszcza fokus albo gdy wskaźnik wybiera obiekt.

public class ColorTap : MonoBehaviour, IMixedRealityFocusHandler, IMixedRealityPointerHandler
{
    private Color color_IdleState = Color.cyan;
    private Color color_OnHover = Color.white;
    private Color color_OnSelect = Color.blue;
    private Material material;

    private void Awake()
    {
        material = GetComponent<Renderer>().material;
    }

    void IMixedRealityFocusHandler.OnFocusEnter(FocusEventData eventData)
    {
        material.color = color_OnHover;
    }

    void IMixedRealityFocusHandler.OnFocusExit(FocusEventData eventData)
    {
        material.color = color_IdleState;
    }

    void IMixedRealityPointerHandler.OnPointerDown(
         MixedRealityPointerEventData eventData) { }

    void IMixedRealityPointerHandler.OnPointerDragged(
         MixedRealityPointerEventData eventData) { }

    void IMixedRealityPointerHandler.OnPointerClicked(MixedRealityPointerEventData eventData)
    {
        material.color = color_OnSelect;
    }
}

Wskaźniki zapytań

Istnieje możliwość zebrania wszystkich wskaźników aktualnie aktywnych przez pętlę za pośrednictwem dostępnych źródeł wejściowych (tj. kontrolerów i dostępnych danych wejściowych), aby dowiedzieć się, które wskaźniki są dołączone do nich.

var pointers = new HashSet<IMixedRealityPointer>();

// Find all valid pointers
foreach (var inputSource in CoreServices.InputSystem.DetectedInputSources)
{
    foreach (var pointer in inputSource.Pointers)
    {
        if (pointer.IsInteractionEnabled && !pointers.Contains(pointer))
        {
            pointers.Add(pointer);
        }
    }
}

Wskaźnik podstawowy

Deweloperzy mogą subskrybować zdarzenie PrimaryPointerChanged FocusProviders, aby otrzymywać powiadomienia o zmianie wskaźnika podstawowego w fokusie. Może to być niezwykle przydatne do zidentyfikowania, czy użytkownik obecnie wchodzi w interakcję ze sceną za pośrednictwem spojrzenia, promienia dłoni lub innego źródła danych wejściowych.

private void OnEnable()
{
    var focusProvider = CoreServices.InputSystem?.FocusProvider;
    focusProvider?.SubscribeToPrimaryPointerChanged(OnPrimaryPointerChanged, true);
}

private void OnPrimaryPointerChanged(IMixedRealityPointer oldPointer, IMixedRealityPointer newPointer)
{
    ...
}

private void OnDisable()
{
    var focusProvider = CoreServices.InputSystem?.FocusProvider;
    focusProvider?.UnsubscribeFromPrimaryPointerChanged(OnPrimaryPointerChanged);

    // This flushes out the current primary pointer
    OnPrimaryPointerChanged(null, null);
}

W PrimaryPointerExample scenie (Assets/MRTK/Examples/Demos/Input/Scenes/PrimaryPointer) pokazano, jak używać PrimaryPointerChangedHandler funkcji , aby zdarzenia odpowiadały na nowy wskaźnik podstawowy.

Przykład wskaźnika podstawowego

Wynik wskaźnika

Właściwość wskaźnika Result zawiera bieżący wynik zapytania sceny używanego do określania obiektu z fokusem. Dla wskaźnika raycast, podobnie jak te utworzone domyślnie dla kontrolerów ruchu, wejście wzroku i promienie dłoni, będzie zawierać lokalizację i normalne trafienie raycast.

private void IMixedRealityPointerHandler.OnPointerClicked(MixedRealityPointerEventData eventData)
{
    var result = eventData.Pointer.Result;
    var spawnPosition = result.Details.Point;
    var spawnRotation = Quaternion.LookRotation(result.Details.Normal);
    Instantiate(MyPrefab, spawnPosition, spawnRotation);
}

Scena PointerResultExample (Assets/MRTK/Examples/Demos/Input/Scenes/PointerResult/PointerResultExample.unity) pokazuje, jak za pomocą wskaźnika Result zduplikować obiekt w lokalizacji trafienia.

Wynik wskaźnika

Wyłączanie wskaźników

Aby włączyć i wyłączyć wskaźniki (na przykład, aby wyłączyć promienie dłoni), ustaw PointerBehavior dla danego typu wskaźnika za pośrednictwem .PointerUtils

// Disable the hand rays
PointerUtils.SetHandRayPointerBehavior(PointerBehavior.AlwaysOff);

// Disable hand rays for the right hand only
PointerUtils.SetHandRayPointerBehavior(PointerBehavior.AlwaysOff, Handedness.Right);

// Disable the gaze pointer
PointerUtils.SetGazePointerBehavior(PointerBehavior.AlwaysOff);

// Set the behavior to match HoloLens 1
// Note, if on HoloLens 2, you must configure your pointer profile to make the GGV pointer show up for articulated hands.
public void SetHoloLens1()
{
    PointerUtils.SetPokePointerBehavior(PointerBehavior.AlwaysOff, Handedness.Any);
    PointerUtils.SetGrabPointerBehavior(PointerBehavior.AlwaysOff, Handedness.Any);
    PointerUtils.SetRayPointerBehavior(PointerBehavior.AlwaysOff, Handedness.Any);
    PointerUtils.SetGGVBehavior(PointerBehavior.Default);
}

Zobacz PointerUtils i TurnPointersOnOff , aby uzyskać więcej przykładów.

Interakcje wskaźnika za pośrednictwem edytora

W przypadku zdarzeń wskaźnika obsługiwanych przez IMixedRealityPointerHandlerelement MRTK zapewnia dalszą wygodę w postaci PointerHandler składnika, który umożliwia obsługę zdarzeń wskaźnika bezpośrednio za pośrednictwem zdarzeń aparatu Unity.

Program obsługi wskaźników

Zakres wskaźnika

Wskaźniki daleko mają ustawienia, które ograniczają, jak daleko będą raycast i wchodzić w interakcje z innymi obiektami w scenie. Domyślnie ta wartość jest ustawiona na 10 metrów. Ta wartość została wybrana, aby zachować spójność z zachowaniem powłoki HoloLens.

Można to zmienić, aktualizując DefaultControllerPointer pola składnika prefab ShellHandRayPointer :

Zakres wskaźnika — określa maksymalną odległość, z którą będą współdziałać wskaźniki.

Domyślny zakres wskaźnika — określa długość wskaźnika/linii, która będzie renderowana, gdy wskaźnik nie wchodzi w interakcję z niczym.

Zobacz też