Wskaźniki

Wskaźnik

W tym artykule wyjaśniono, jak skonfigurować dane wejściowe wskaźnika i reagować na nie w praktyce w porównaniu z architekturą 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 w przypadku domyślnego profilu wskaźnika kontrolery Windows Mixed Reality uzyskać zarówno linię, jak i wskaźnik paraboliczny dla prawidłowego wyboru i pomięć.

Konfiguracja wskaźnika

Wskaźniki są konfigurowane jako część systemu wejściowego w mrTK za pośrednictwem MixedRealityPointerProfile . Ten typ profilu jest przypisywany do obiektu MixedRealityInputSystemProfile w inspektorze konfiguracji MRTK. Profil Wskaźnik określa kursor, typy wskaźników dostępnych w czasie wykonywania oraz sposób, w jaki te wskaźniki komunikują się ze sobą, aby zdecydować, który z nich jest aktywny.

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

  • Wskazuje maski warstwy Raycast — jest to uporządkowana priorytetowo tablica masek warstwowych w celu określenia, z którymi obiektami GameObject może wchodzić dowolny wskaźnik, oraz kolejnością interakcji do próby. Może to być przydatne do zapewnienia, że wskaźniki wchodzą w interakcję z elementami interfejsu użytkownika przed innymi obiektami sceny. Przykład profilu wskaźnika

Konfiguracja opcji wskaźnika

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

Przykład profilu opcji wskaźnika

Każdy wpis Wskaźnik 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 "poking" obiektów z palcem i jest domyślnie oznaczony jako obsługujący tylko typ kontrolera ręki. Wskaźniki są tworzone tylko wtedy, gdy kontroler staje się dostępny, a w szczególności typ kontrolera definiuje, za pomocą których kontrolerów można utworzyć ten prefabrykat wskaźnika.
  • Handedness —umożliwia tworzenie wystąpienia wskaźnika tylko dla określonej ręki (lewa/prawa)

Uwaga

Ustawienie właściwości Handedness wpisu Wskaźnik na wartość None skutecznie wyłączy ją z systemu jako alternatywę do usunięcia tego wskaźnika z listy.

  • Prefabrykat wskaźnika — ten wstępny zasób zostanie uruchomiony, gdy kontroler zgodny z określonym typem kontrolera i zasobnością zacznie być śledzony.

Istnieje możliwość mieć wiele wskaźników skojarzonych z kontrolerem. Na przykład w programie DefaultHoloLens2InputSystemProfile (Assets/MRTK/SDK/Profiles/HoloLens2/) układowy kontroler skojarzony jest z narzędziami DefaultHoloLens2InputSystemProfileGrabPointeri DefaultControllerPointer (czyli promieniami ręki).

Uwaga

Zestaw mrTK zawiera zestaw prefabryktów wskaźników w zestawie Assets/MRTK/SDK/Features/UX/Prefabs/Pointers. Nową niestandardową prefabrykcję można stworzyć, o ile zawiera ona jeden ze skryptów wskaźników w plikach Assets/MRTK/SDK/Features/UX/Scripts/Pointers lub dowolny inny skrypt implementowania .

Konfiguracja kursora

Kursor Spojrzenie można bezpośrednio skonfigurować za pośrednictwem GazeCursorPrefab właściwości w MixedRealityInputSystemProfile edytorze. Aby skonfigurować kursor używany dla innych wskaźników, musisz zmienić prefabrykcję używaną w polu CursorPrefab odpowiedniego wskaźnika BaseControllerPointer . Aby programowo zmienić kursor, zmodyfikuj BaseCursor właściwość odpowiedniego IMixedRealityPointer zachowania.

Właściwość prefabrykcyjna kursora

Zobacz nasze prefabrykaty kursora w tece Assets/MRTK/SDK/Features/UX/Prefabs/Cursors, aby uzyskać przykładowe 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

Następujące klasy to dostępne i zdefiniowane w domyślnym profilu wskaźnika MRTK opisane powyżej wskaźniki mrtk. Każdy prefabrykant wskaźnika w obszarze Assets/MRTK/SDK/Features/UX/Prefabs/Pointers zawiera jeden z dołączonych składników wskaźnika.

Wskaźniki domyślne MRTK

Wskaźniki daleko

LinePointer

LinePointer, klasa wskaźnika podstawowego, rysuje linię ze źródła danych wejściowych (tj. kontrolera) w kierunku wskaźnika i obsługuje rzutowanie pojedynczego promienia w tym kierunku. Ogólnie rzecz biorąc, klasy dzieci, takie jak i wskaźniki teleportacji, są cytowane i używane (które również rysują linie wskazujące, gdzie zakończy się teleportacja), zamiast tej klasy, która głównie zapewnia wspólne ShellHandRayPointer funkcje.

W przypadku kontrolerów ruchu, takich jak Oculus, Vive i Windows Mixed Reality, obrót będzie odpowiadać rotacji kontrolera. W przypadku innych kontrolerów, takich HoloLens 2, kąt obrotu pasuje do układu ręki w punkcie dostarczonym przez system.

Linia wskaźnika MRTK
CurvePointer

CurvePointer rozszerzaklasę LinePointer, umożliwiając rzutowania wieloetapowe promienie wzdłuż krzywej. Ta klasa wskaźnika podstawowego jest przydatna w przypadku zakrzywionych wystąpień, takich jak wskaźniki teleportacji, w których linia stale znajduje się w paraboli.

ShellHandRayPointer

Implementacja narzędzia ShellHandRayPointer,która rozszerza zakres od , jest używana jako domyślna dla profilu wskaźnika MRTK. DefaultControllerPointer prefab implementuje klasę.

GGVPointer

Znany również jako wskaźnik Spojrzenie/Gest/Głos (GGV), GGVPointer umożliwia interakcję z jednym wyglądem i naciśnięciem w stylu HoloLens, przede wszystkim za pośrednictwem interakcji Spojrzenie i naciśnięcie w powietrzu lub Spojrzenia i głos Select. Położenie i kierunek wskaźnika GGV są sterowane położeniem i rotacją głowy.

TouchPointer

Program TouchPointer jest odpowiedzialny za pracę z wprowadzaniem danych wejściowych aparatu Unity Touch (tj. ekranem dotykowym). Są to "daleko dostępne interakcje", ponieważ dotknięcie ekranu spowoduje rzutowanie promienia z kamery do potencjalnie daleko dostępnej lokalizacji w scenie.

MousePointer

MousePointer zasila ekran do świata raycast do wielu interakcji, ale myszy zamiast dotyku.

Wskaźnik myszy

Uwaga

Obsługa myszy nie jest domyślnie dostępna w mrTK, ale można ją włączyć przez dodanie nowego Dostawca danych wejściowego typu do profilu wejściowego mrtk i przypisanie obiektu do dostawcy MixedRealityMouseInputProfile danych.

Wskaźniki blisko

PokePointer

Obiekt PokePointer jest używany do interakcji z obiektami gry, które obsługują "niemal interakcję dotykową". są toobiekty GameObject z dołączonym NearInteractionTouchable skryptem. W przypadku aparatu UnityUI ten wskaźnik wyszukuje jednostki NearInteractionTouchableUnityUIs. Element PokePointer używa spherecast do określenia najbliższego elementu dotykowego i jest używany do zasilania elementów, takich jak przyciski naciskalne.

Podczas konfigurowania obiektu GameObject za pomocą składnika upewnij się, że skonfigurowano parametr localForward, aby wskazać z przodu przycisku lub innego obiektu, który powinien być NearInteractionTouchable dotykowy. NearInteractionTouchable Upewnij się również, że granice obiektu dotkowalnego są takie, jak granice obiektu dotkowalnego.

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

  • TouchableDistance:maksymalna odległość, z jaką można wchodzić w interakcję z powierzchnią dotykową
  • Wizualizacje:obiekt game używany do renderowania wizualizacji wierzchołka palca (domyślnie pierścień na palecie).
  • Linia:opcjonalna linia do rysowania od ręki do aktywnej powierzchni wejściowej.
  • Maski warstwy poke — uporządkowana priorytetowo tablica masek warstwowych w celu określenia, z którymi obiektami GameObject może wchodzić wskaźnik w interakcję, oraz kolejności interakcji do próby. Należy pamiętać, że obiekt GameObject musi również mieć składnik, aby można było wchodzić w interakcje NearInteractionTouchable ze wskaźnikiem poke.
Wskaźnik poke
SpherePointer

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

Chwyć wskaźnik

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

  • Promień rzutowaniasfery: promień dla sfery używany do wykonywania zapytań o obiekty do chwytowania.
  • Blisko marginesu obiektu:odległość na górze promienia rzutowania sfery do zapytania w celu wykrycia, czy obiekt znajduje się w pobliżu wskaźnika. Łączny promień wykrywania obiektu najbliższego to Promień rzutowania sfery + margines blisko obiektu
  • Near Object Sector Angle( Kąt sektora obiektu): kąt wokół osi do przodu wskaźnika do wykonywania zapytań o obiekty w pobliżu. Sprawia, IsNearObject że zapytanie działa jak rąbek. Ta wartość jest domyślnie ustawiona na 66 stopni, aby dopasować zachowanie urządzenia Hololens 2

Wskaźnik sfery zmodyfikowany w celu wykonywania zapytań tylko o obiekty w kierunku do przodu

  • Near Object Smoothing Factor:współczynnik wygładniania dla wykrywania bliskich obiektów. Jeśli obiekt zostanie wykryty w promieniu najbliższego obiektu, promienia, do których dotyczy zapytanie, staje się wartością Near Object Radius * (1 + współczynnik wygładania obiektu najbliższego), aby zmniejszyć czułość i utrudnić opuszczenie zakresu wykrywania przez obiekt.
  • Chwyć maski warstw — uporządkowaną priorytetowo tablicę masek warstw w celu określenia, z którymi obiektami GameObject może wchodzić wskaźnik w interakcję, oraz kolejności interakcji, z którymi może podejmować próby. Należy pamiętać, że obiekt GameObject musi również mieć obiekt , aby można było wchodzić w interakcję NearInteractionGrabbable z obiektem SpherePointer.

    Uwaga

    Warstwa świadomości przestrzennej jest wyłączona w domyślnej prefabrykcie programu GrabPointer dostarczonym przez mrTK. Ma to na celu zmniejszenie wpływu na wydajność wykonywania zapytania nakładania się sfery z siatką przestrzenną. Można to włączyć, modyfikując prefabrykcję programu GrabPointer.

  • Ignoruj elementy collider not in FOV (Ignorowanie elementów collider poza fov) — czy należy ignorować elementy collider, które mogą być w pobliżu wskaźnika, ale nie są faktycznie w wizualnym fov. Może to zapobiec przypadkowemu chwyceniu i umożliwi włączenie promieni dłoni, gdy możesz być blisko chwytnego, ale go nie widzisz. Wizualne fov jest definiowane za pośrednictwem rębka zamiast typowego frustum ze względu na wydajność. Ten rąbek jest wyśrodkowany i zorientowany tak samo jak frustum aparatu z promieniem równym połowie wysokości wyświetlania (lub pionowego fov).
Wskaźnik sfery

Wskaźniki teleportacji

  • TeleportPointer Spowoduje to zgłoszenie żądania resetu po podjętej akcji (tj. naciśnięciu przycisku resetu) w celu przeniesienia użytkownika.
  • ParabolicTeleportPointer Spowoduje to zgłoszenie żądania resetu po akcji (tj. naciśnięciu przycisku resetu) z paraboliczną linią raycast w celu przeniesienia użytkownika.
Wskaźnik paraboliczny

Obsługa wskaźników dla platform rzeczywistości mieszanej

W poniższej tabeli przedstawiono typy wskaźników, które są zwykle używane dla typowych platform w plice MRTK. UWAGA: do tych platform można dodać różne typy wskaźników. Możesz 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źników za pośrednictwem kodu

Interfejsy zdarzeń wskaźnika

MonoBehaviours, które implementują co najmniej jeden z następujących interfejsów i są przypisane do gameObject za pomocą typu , otrzymają zdarzenia interakcji wskaźnika zgodnie z definicją w Collider skojarzonym interfejsie.

Zdarzenie Opis Program obsługi
Przed zmianą fokusu/zmiana fokusu Podniesiony zarówno na obiekcie gry, który traci fokus, jak i tym, który zyskuje go za każdym razem, gdy wskaźnik zmienia fokus. IMixedRealityFocusChangedHandler
Wprowadzanie/zamykanie fokusu Podniesiony na obiekcie gry, zyskując fokus, gdy wchodzi do niego pierwszy wskaźnik, i na tym, który traci fokus, gdy ostatni wskaźnik opuszcza go. IMixedRealityFocusHandler
Wskaźnik w dół/przeciągnięty/w górę/kliknięty Podniesiono do raportu naciśnięcie wskaźnika, przeciągnięcie i zwolnienie. IMixedRealityPointerHandler
Touch Started/Updated/Completed (Dotyk rozpoczęty/zaktualizowany/ukończony) Podniesione przez wskaźniki z dotykową, takie PokePointer jak, aby zgłaszać aktywność dotykową. IMixedRealityTouchHandler

Uwaga

IMixedRealityFocusChangedHandler i IMixedRealityFocusHandler powinny być obsługiwane w obiektach, na których są one wywoływane. Zdarzenia fokusu można odbierać globalnie, ale w przeciwieństwie do innych zdarzeń wejściowych globalna procedura obsługi zdarzeń nie zablokuje odbierania zdarzeń na podstawie fokusu (zdarzenie zostanie odebrane zarówno przez globalny program obsługi, jak i odpowiedni obiekt w fokusie).

Działanie zdarzeń wejściowych wskaźnika

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 polega na tym, że zdarzenia wejściowe wskaźnika są obsługiwane tylko przez gameobject w trybie koncentracji uwagi przez wskaźnik, który wyzłożył zdarzenie wejściowe, a także przez wszystkie globalne programy obsługi danych wejściowych. Regularne zdarzenia wejściowe są obsługiwane przez fokus GameObjects dla wszystkich aktywnych wskaźników.

  1. System wejściowy MRTK rozpoznaje, że wystąpiło zdarzenie wejściowe
  2. System wejściowy MRTK wyzje odpowiednią funkcję interfejsu dla zdarzenia wejściowego do wszystkich zarejestrowanych globalnych programów obsługi danych wejściowych
  3. System wejściowy określa, który projekt GameObject koncentruje się na wskaźniku, który wyzłożył zdarzenie
    1. System wejściowy używa systemu zdarzeń aparatu Unity do obsługi odpowiedniej funkcji interfejsu dla wszystkich pasujących składników w ukierunkowanych elementach GameObject
    2. Jeśli w dowolnym momencie zdarzenie wejściowe zostało oznaczone jako użyte,proces zakończy się i żadne dalsze punkty GameObjects nie będą otrzymywać wywołań zwrotnych.
      • Przykład: Składniki implementujące interfejs będą wyszukiwane w poszukiwaniu korzyści lub utraty fokusu w IMixedRealityFocusHandler gameobject
      • Uwaga: System zdarzeń aparatu Unity będzie bąbelkowy przeszukiwać nadrzędny obiekt GameObject, jeśli w bieżącym obiekcie GameObject nie zostaną znalezione żadne składniki pasujące do żądanego interfejsu.
  4. Jeśli żadne globalne programy obsługi danych wejściowych nie zostaną zarejestrowane i nie zostanie znaleziony żaden element GameObject z pasującymi składnikami/interfejsami, system wejściowy wywoła wszystkie rezerwowe zarejestrowane programy obsługi danych wejściowych

Przykład

Poniżej znajduje się przykładowy skrypt, który zmienia kolor dołączonego programu renderowego, gdy wskaźnik przyjmuje fokus lub pozostawia fokus lub gdy wskaźnik wybierze 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 aktualnie aktywnych wskaźników przez zapętlenie dostępnych źródeł danych wejściowych (tj. dostępnych kontrolerów i danych wejściowych), aby wykryć, które wskaźniki są do nich dołączone.

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 FocusProviders PrimaryPointerChanged, aby być powiadamiane o zmianie podstawowego wskaźnika fokusu. Może to być bardzo przydatne do określenia, czy użytkownik aktualnie wchodzi w interakcję ze sceną za pośrednictwem spojrzenia, promienia ręki 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ć metody dla zdarzeń w celu reagowania na nowy PrimaryPointerChangedHandler wskaźnik podstawowy.

Przykład wskaźnika podstawowego

Wynik wskaźnika

Właściwość pointer Result zawiera bieżący wynik zapytania sceny używanego do określenia obiektu z fokusem. W przypadku wskaźnika emisji promieniowej, takiego jak te utworzone domyślnie dla kontrolerów ruchu, danych wejściowych spojrzenia i promieni ręki, będzie on zawierać lokalizację i normalną lokalizację trafienia 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 zduplikować obiekt w lokalizacji Result trafienia.

Wynik wskaźnika

Wyłączanie wskaźników

Aby włączyć i wyłączyć wskaźniki (na przykład w celu wyłączenia promienia dłoni), ustaw dla danego typu wskaźnika PointerBehavior za pomocą . 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 , aby uzyskać więcej TurnPointersOnOff przykładów.

Interakcje wskaźników za pośrednictwem edytora

W przypadku zdarzeń wskaźnika obsługiwanych przez usługę MRTK zapewnia dodatkowe udogodnienie w postaci składnika, co umożliwia obsługę zdarzeń wskaźnika bezpośrednio za pośrednictwem zdarzeń IMixedRealityPointerHandlerPointerHandler aparatu Unity.

Program obsługi wskaźnika

Zakres wskaźnika

Wskaźniki o dalece mają ustawienia, które ograniczają, jak daleko będą promieniowały i wchodziły 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 HoloLens powłoki.

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

Zakres wskaźnika — określa maksymalną odległość, z pomocą których będą wchodzić wskaźniki.

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

Zobacz też