Wskaźniki — MRTK2
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.
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.
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 BaseControllerPointer
elementu . Aby zmienić kursor programowo, zmodyfikuj BaseCursor
właściwość odpowiedniego IMixedRealityPointer
zachowania.
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.
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ę.
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.
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.
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
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
- 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ź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.
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.
- System wejściowy MRTK rozpoznaje zdarzenie wejściowe wystąpiło
- System wejściowy MRTK uruchamia odpowiednią funkcję interfejsu dla zdarzenia wejściowego dla wszystkich zarejestrowanych globalnych procedur obsługi danych wejściowych
- System wejściowy określa, który obiekt GameObject znajduje się w fokusie dla wskaźnika, który wystrzelił zdarzenie
- 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
- 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.
- Przykład: Składniki implementowane interfejsu
- 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.
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.
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 IMixedRealityPointerHandler
element 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.
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.