Kontrolery ruchu w a unity

Istnieją dwa kluczowe sposoby podejmowania akcji na spojrzeniu w akwenie Unity, gesty dłoni i kontrolery ruchu na urządzeniach HoloLens i immersywne HMD. Uzyskujesz dostęp do danych dla obu źródeł danych wejściowych przestrzennych za pomocą tych samych interfejsów API w a unity.

Aparat Unity zapewnia dwa podstawowe sposoby uzyskiwania dostępu do danych wejściowych przestrzennych dla Windows Mixed Reality. Typowe interfejsy API Input.GetButton/Input.GetAxis działają w wielu zestawach SDK XR aparatu Unity, podczas gdy interfejs API InteractionManager/GestureRecognizer specyficzny dla Windows Mixed Reality uwidacznia pełny zestaw danych wejściowych przestrzennych.

Interfejsy API wejściowe XR aparatu Unity

W przypadku nowych projektów zalecamy używanie nowych interfejsów API wejściowych XR od początku.

Więcej informacji na temat interfejsów API XR można znaleźć tutaj.

Tabela mapowania przycisku/osi aparatu Unity

Menedżer danych wejściowych aparatu Unity dla kontrolerów ruchu Windows Mixed Reality obsługuje identyfikatory przycisków i osi wymienionych poniżej za pośrednictwem interfejsów API Input.GetButton/GetAxis. Kolumna "Specyficzne dla języka MR systemu Windows" odwołuje się do właściwości dostępnych poza typem InteractionSourceState . Każdy z tych interfejsów API został szczegółowo opisany w poniższych sekcjach.

Mapowania identyfikatorów przycisków/osi dla Windows Mixed Reality zazwyczaj pasują do identyfikatorów przycisków/osi Oculus.

Mapowania identyfikatorów przycisków/osi dla Windows Mixed Reality różnią się od mapowań interfejsu OpenVR na dwa sposoby:

  1. Mapowanie używa identyfikatorów touchpad, które różnią się od szminki, do obsługi kontrolerów z zarówno kciukami, jak i touchpadami.
  2. Mapowanie pozwala uniknąć przeciążenia identyfikatorów przycisków A i X przycisków menu, aby pozostawić je dostępne dla fizycznych przycisków ABXY.
Dane wejścioweTypowe interfejsy API aparatu Unity
(Input.GetButton/GetAxis)
Interfejs API danych wejściowych specyficznych dla systemu Windows
(XR. WSA. Dane wejściowe)
Lewej Prawej
Wybieranie wyzwalacza naciśniętego Oś 9 = 1,0 Oś 10 = 1,0 selectPressed
Wybierz wartość analogową wyzwalacza Oś 9 Oś 10 selectPressedAmount
Wybierz wyzwalacz częściowo naciśnięty Przycisk 14 (gamepad compat) Przycisk 15 (gamepad compat) selectPressedAmount > 0.0
Naciśnięcie przycisku menu Przycisk 6* Przycisk 7* menuPressed
Naciśnięcie przycisku uchwytu Oś 11 = 1,0 (bez wartości analogowych)
Przycisk 4 (gamepad compat)
Oś 12 = 1,0 (bez wartości analogowych)
Przycisk 5 (gamepad compat)
Uchwycić
Kciuk X (po lewej: -1.0, po prawej: 1.0) Oś 1 Oś 4 thumbstickPosition.x
Kciuk Y (góra: -1.0, u dołu: 1.0) Oś 2 Oś 5 thumbstickPosition.y
Naciśnięty kciuk Przycisk 8 Przycisk 9 thumbstickPressed
Touchpad X (po lewej: -1.0, po prawej: 1.0) Oś 17* Oś 19* touchpadPosition.x
Touchpad Y (góra: -1.0, u dołu: 1.0) Oś 18* Oś 20* touchpadPosition.y
Touchpad dotknął Przycisk 18* Przycisk 19* touchpadTouched
Naciśnięcie touchpadu Przycisk 16* Przycisk 17* touchpadPressed
6DoF uchwyt pozuje lub wskaźnik pozy Uchwyt pozuje tylko: XR. InputTracking.GetLocalPosition
Xr. InputTracking.GetLocalRotation
Przekaż uchwyt lub wskaźnik jako argument: sourceState.sourcePose.TryGetPosition
sourceState.sourcePose.TryGetRotation
Stan śledzenia Dokładność położenia i ryzyko utraty źródła dostępne tylko za pośrednictwem interfejsu API specyficznego dla mr sourceState.sourcePose.positionAccuracy
sourceState.properties.sourceLossRisk

Uwaga

Te identyfikatory przycisków/osi różnią się od identyfikatorów używanych przez aparat Unity dla openVR z powodu kolizji w mapowaniach używanych przez gamepady, Oculus Touch i OpenVR.

OpenXR

Aby dowiedzieć się więcej na temat interakcji rzeczywistości mieszanej w a środowisku Unity, odwiedź stronę Podręcznik aparatu Unity dla danych wejściowych XR aparatu Unity. W tej dokumentacji aparatu Unity omówiono mapowania z danych wejściowych specyficznych dla kontrolera na bardziej uogólnialne dane wejściowe InputFeatureUsage, sposób identyfikowaniai kategoryzowania dostępnych danych wejściowych XR, odczytywania danych z tych danych wejściowych i nie tylko.

Wtyczka Mixed Reality OpenXR udostępnia dodatkowe profile interakcji wejściowych, mapowane na standardowe inputFeatureUsage, jak opisano poniżej:

InputFeatureUsage Kontroler HP Reverb G2 (OpenXR) HoloLens Hand (OpenXR)
primary2DAxis Joystick
primary2DAxisKlick Joystick - Click
spust Wyzwalacz
chwyt Chwyt Naciśnięcie lub wycisnięcie powietrza
primaryButton [X/A] - Naciśnij Naciśnięcie w powietrzu
secondaryButton [Y/B] - Naciśnij
gripButton Uchwyt — naciśnięcie
triggerButton Wyzwalacz — naciśnięcie klawisza
menuButton Menu

Pozowanie uchwytu w porównaniu z pozą wskazującą

Windows Mixed Reality obsługuje kontrolery ruchu w różnych kształtach. Projekt każdego kontrolera różni się w zależności od położenia ręki użytkownika i naturalnego kierunku "do przodu", którego aplikacje powinny używać do wskazywania podczas renderowania kontrolera.

Aby lepiej reprezentować te kontrolery, istnieją dwa rodzaje pozy, które można zbadać dla każdego źródła interakcji, pozycja uchwytu i pozycja wskaźnika. Zarówno położenie uchwytu, jak i wskaźnik stanowią współrzędne, są wyrażane przez wszystkie interfejsy API aparatu Unity we współrzędnych świata globalnej aparatu Unity.

Pozycja uchwytu

Pozycja uchwytu reprezentuje lokalizację dłoni użytkowników, wykrytą przez urządzenie HoloLens lub trzymając kontroler ruchu.

W immersywnych zestawach nagłownych uchwyt najlepiej użyć do renderowania ręki użytkownika lub obiektu trzymanego w ręku użytkownika. Pozycja uchwytu jest również używana podczas wizualizowania kontrolera ruchu. Model renderowalny dostarczony przez system Windows dla kontrolera ruchu używa uchwytu jako źródła i środka obrotu.

Pozycja uchwytu jest definiowana w następujący sposób:

  • Położenie uchwytu: centroid palmowy przytrzymując kontroler naturalnie, wyregulowany w lewo lub w prawo, aby wyśrodkować położenie w uchwytie. Na kontrolerze ruchu Windows Mixed Reality ta pozycja zazwyczaj jest wyrównana z przyciskiem Uchwyt.
  • Oś prawa orientacji uchwytu: Kiedy całkowicie otworzysz rękę, aby utworzyć płaską 5-palcową pozę, promienie, które jest normalne dla dłoni (do przodu z lewej dłoni, do tyłu od prawej dłoni)
  • Oś przodu orientacji uchwytu: Po zamknięciu ręki częściowo (jakby przytrzymanie kontrolera), promienia, który wskazuje "do przodu" przez rurkę utworzoną przez palce bez kciuka.
  • Oś uścisku Oś w górę: oś w górę dorozumiana przez definicje Prawe i Do przodu.

Dostęp do uchwytu można uzyskać za pośrednictwem interfejsu API wejściowego między dostawcami (XR) aparatu Unity. InputTracking. GetLocalPosition/Rotation) lub za pośrednictwem interfejsu API specyficznego dla zestawu narzędzi MR systemu Windows (sourceState.sourcePose.TryGetPosition/Rotation, żądając podania danych dla węzła uchwytu ).

Pozycja wskaźnika

Pozycja wskaźnika reprezentuje końcówkę kontrolera wskazującą do przodu.

Wskaźnik dostarczony przez system najlepiej nadaje się do raycast podczas renderowania samego modelu kontrolera. W przypadku renderowania innego wirtualnego obiektu zamiast kontrolera, takiego jak pistolet wirtualny, należy wskazać promienie najbardziej naturalne dla tego obiektu wirtualnego, takie jak ray, który podróżuje wzdłuż beczki modelu pistoletu zdefiniowanego przez aplikację. Ponieważ użytkownicy mogą zobaczyć obiekt wirtualny, a nie kontroler fizyczny, wskazywanie za pomocą obiektu wirtualnego prawdopodobnie będzie bardziej naturalne dla użytkowników korzystających z aplikacji.

Obecnie pozycja wskaźnika jest dostępna w amencie Unity tylko za pośrednictwem interfejsu API specyficznego dla języka MR systemu Windows , sourceState.sourcePose.TryGetPosition/Rotation, przekazując element InteractionSourceNode.Pointer jako argument.

OpenXR

Masz dostęp do dwóch zestawów pozy za pośrednictwem interakcji wejściowych OpenXR:

  • Uchwyt stanowi do renderowania obiektów w ręku
  • Celem jest wskazywanie na świat.

Więcej informacji na temat tego projektu i różnic między nimi można znaleźć w temacie Specyfikacja OpenXR — ścieżki podrzędne wejściowe.

Pozuje dostarczone przez InputFeatureUsages DevicePosition, DeviceRotation, DeviceVelocity i DeviceAngularVelocity wszystkie reprezentują pozycję uchwytu OpenXR. InputFeatureUsages związane z pozami uchwytu są definiowane w commonUsages aparatu Unity.

Pozy dostarczane przez element InputFeatureUsages PointerPosition, PointerRotation, PointerVelocity i PointerAngularVelocity reprezentują pozę celu OpenXR. Te pliki InputFeatureUsages nie są zdefiniowane w żadnych dołączonych plikach języka C#, dlatego należy zdefiniować własne dane InputFeatureUsages w następujący sposób:

public static readonly InputFeatureUsage<Vector3> PointerPosition = new InputFeatureUsage<Vector3>("PointerPosition");

Haptyki

Aby uzyskać informacje na temat używania haptyki w systemie wprowadzania XR aparatu Unity, dokumentację można znaleźć w podręczniku aparatu Unity dla danych wejściowych aparatu Unity XR — haptics.

Stan śledzenia kontrolera

Podobnie jak zestawy słuchawkowe, kontroler ruchu Windows Mixed Reality nie wymaga konfiguracji zewnętrznych czujników śledzenia. Zamiast tego kontrolery są śledzone przez czujniki w samym zestawie słuchawkowym.

Jeśli użytkownik przenosi kontrolery z pola widoku zestawu nagłownego, system Windows nadal wywnioskuje pozycje kontrolera w większości przypadków. Gdy kontroler utracił śledzenie wizualne na tyle długo, pozycje kontrolera spadną do przybliżonych pozycji dokładności.

W tym momencie system zablokuje kontrolerowi treść, śledząc pozycję użytkownika podczas poruszania się, a jednocześnie ujawniając prawdziwą orientację kontrolera przy użyciu wewnętrznych czujników orientacji. Wiele aplikacji, które używają kontrolerów do wskazywania i aktywowania elementów interfejsu użytkownika, może działać normalnie, podczas gdy przybliżona dokładność nie jest widoczna dla użytkownika.

Jawne wnioskowanie o stanie śledzenia

Aplikacje, które chcą traktować pozycje inaczej na podstawie stanu śledzenia, mogą pójść dalej i sprawdzić właściwości stanu kontrolera, takie jak SourceLossRisk i PositionAccuracy:

Stan śledzenia SourceLossRisk PositionAccuracy TryGetPosition
Wysoka dokładność < 1.0 Wys. true
Wysoka dokładność (ryzyko utraty) == 1.0 Wys. true
Przybliżona dokładność == 1.0 Przybliżony true
Brak położenia == 1.0 Przybliżony fałsz

Te stany śledzenia kontrolera ruchu są definiowane w następujący sposób:

  • Wysoka dokładność: Kontroler ruchu znajduje się w polu widzenia zestawu nagłownego, ale zazwyczaj zapewnia wysoką dokładność pozycji na podstawie śledzenia wizualnego. Ruchomy kontroler, który chwilowo opuszcza pole widoku lub jest chwilowo zasłonięty z czujników zestawu nagłownego (np. z drugiej strony) będzie nadal zwracać wysoką dokładność przez krótki czas, w oparciu o inertyjne śledzenie samego kontrolera.
  • Wysoka dokładność (ryzyko utraty): Gdy użytkownik przesuwa kontroler ruchu obok krawędzi pola widoku zestawu słuchawkowego, zestaw słuchawkowy wkrótce nie będzie mógł wizualnie śledzić położenia kontrolera. Aplikacja wie, kiedy kontroler osiągnął tę granicę FOV, widząc SourceLossRisk osiągnąć 1.0. W tym momencie aplikacja może zdecydować się na wstrzymanie gestów kontrolera, które wymagają stałego strumienia wysokiej jakości.
  • Przybliżona dokładność: Gdy kontroler utracił śledzenie wizualne na tyle długo, pozycje kontrolera spadną do przybliżonych pozycji dokładności. W tym momencie system zablokuje kontrolerowi treść, śledząc pozycję użytkownika podczas poruszania się, a jednocześnie ujawniając prawdziwą orientację kontrolera przy użyciu wewnętrznych czujników orientacji. Wiele aplikacji, które używają kontrolerów do wskazywania i aktywowania elementów interfejsu użytkownika, może działać tak normalnie, jak w przybliżonej dokładności bez notowania użytkownika. Aplikacje z cięższymi wymaganiami wejściowymi mogą zdecydować się na to spadek z wysokiej dokładności do przybliżonej dokładności, sprawdzając właściwość PositionAccuracy , na przykład, aby dać użytkownikowi bardziej hojny hitbox na miejscach docelowych poza ekranem w tym czasie.
  • Brak pozycji: Chociaż kontroler może działać w przybliżonej dokładności przez długi czas, czasami system wie, że nawet pozycja zablokowana treść nie ma znaczenia w tej chwili. Na przykład kontroler, który został włączony, mógł nigdy nie zostać zaobserwowany wizualnie lub użytkownik może odłożyć kontroler, który następnie zostanie odebrany przez kogoś innego. W tym czasie system nie udostępni żadnej pozycji aplikacji, a funkcja TryGetPosition zwróci wartość false.

Typowe interfejsy API aparatu Unity (Input.GetButton/GetAxis)

Przestrzeń nazw:UnityEngine, UnityEngine.XR
Typy: Dane wejściowe, XR. InputTracking

Aparat Unity używa obecnie ogólnych interfejsów API Input.GetButton/Input.GetAxis w celu uwidocznienia danych wejściowych dla zestawu Oculus SDK, zestawu OpenVR SDK i Windows Mixed Reality, w tym kontrolerów rąk i ruchu. Jeśli aplikacja używa tych interfejsów API do wprowadzania danych wejściowych, może łatwo obsługiwać kontrolery ruchu w wielu zestawach SDK XR, w tym Windows Mixed Reality.

Pobieranie stanu naciśnięcia przycisku logicznego

Aby użyć ogólnych interfejsów API wejściowych aparatu Unity, zazwyczaj należy rozpocząć od podłączenia przycisków i osi do nazw logicznych w menedżerze danych wejściowych aparatu Unity, powiązania przycisku lub identyfikatorów osi z każdą nazwą. Następnie możesz napisać kod odwołujący się do tej nazwy przycisku logicznego/osi.

Aby na przykład zamapować przycisk wyzwalacza lewego kontrolera ruchu na akcję Prześlij, przejdź do pozycji Edytuj > dane wejściowe ustawień > projektu w a także rozwiń właściwości sekcji Prześlij w obszarze Osie. Zmień właściwość Przycisk dodatni lub Alt Positive Button , aby odczytać przycisk Przycisku 14, w następujący sposób:

InputManager aparatu Unity
Unity InputManager

Skrypt może następnie wyszukać akcję Prześlij przy użyciu metody Input.GetButton:

if (Input.GetButton("Submit"))
{
  // ...
}

Możesz dodać więcej przycisków logicznych, zmieniając właściwość Size w obszarze Osie.

Bezpośrednie naciśnięcie przycisku fizycznego

Możesz również ręcznie uzyskiwać dostęp do przycisków przy użyciu ich w pełni kwalifikowanej nazwy przy użyciu metody Input.GetKey:

if (Input.GetKey("joystick button 8"))
{
  // ...
}

Uzyskiwanie pozy kontrolera ruchu lub ręki

Dostęp do położenia i rotacji kontrolera można uzyskać za pomocą XR. InputTracking:

Vector3 leftPosition = InputTracking.GetLocalPosition(XRNode.LeftHand);
Quaternion leftRotation = InputTracking.GetLocalRotation(XRNode.LeftHand);

Uwaga

Powyższy kod reprezentuje pozycję uchwytu kontrolera (gdzie użytkownik posiada kontroler), co jest przydatne do renderowania miecza lub pistoletu w ręku użytkownika lub modelu samego kontrolera.

Relacja między tym uchwytem a wskaźnikiem (gdzie wskazówka kontrolera wskazuje) może się różnić między kontrolerami. W tej chwili uzyskiwanie dostępu do pozy wskaźnika kontrolera jest możliwe tylko za pośrednictwem interfejsu API danych wejściowych specyficznych dla języka MR opisanego w poniższych sekcjach.

Interfejsy API specyficzne dla systemu Windows (XR). WSA. Dane wejściowe)

Przestroga

Jeśli projekt korzysta z dowolnego Z XR. Interfejsy API WSA są one wycofywane na rzecz zestawu SDK XR w przyszłych wersjach aparatu Unity. W przypadku nowych projektów zalecamy używanie zestawu SDK XR od początku. Więcej informacji na temat systemu danych wejściowych XR i interfejsów API można znaleźć tutaj.

Przestrzeń nazw:UnityEngine.XR.WSA.Input
Typy: InteractionManager, InteractionSourceState, InteractionSource, InteractionSourceProperties, InteractionSourceKind, InteractionSourceLocation

Aby uzyskać bardziej szczegółowe informacje na temat Windows Mixed Reality danych wejściowych (dla urządzeń HoloLens) i kontrolerów ruchu, możesz użyć interfejsów API danych wejściowych przestrzennych specyficznych dla systemu Windows w przestrzeni nazw UnityEngine.XR.WSA.Input. Dzięki temu można uzyskać dostęp do dodatkowych informacji, takich jak dokładność położenia lub rodzaj źródła, dzięki czemu można odróżnić ręce i kontrolery.

Sondowanie stanu rąk i kontrolerów ruchu

Możesz sondować stan tej ramki dla każdego źródła interakcji (ręcznego lub kontrolera ruchu) przy użyciu metody GetCurrentReading .

var interactionSourceStates = InteractionManager.GetCurrentReading();
foreach (var interactionSourceState in interactionSourceStates) {
    // ...
}

Każdy element InteractionSourceState , który otrzymujesz, reprezentuje źródło interakcji w bieżącej chwili w czasie. Element InteractionSourceState uwidacznia informacje, takie jak:

  • Jakie rodzaje naciśnięcia występują (Select/Menu/Grasp/Touchpad/Thumbstick)

    if (interactionSourceState.selectPressed) {
         // ...
    }
    
  • Inne dane specyficzne dla kontrolerów ruchu, takie jak touchpad i/lub pałeczka XY współrzędnych XY i stan dotyku

    if (interactionSourceState.touchpadTouched && interactionSourceState.touchpadPosition.x > 0.5) {
         // ...
    }
    
  • InteractionSourceKind dowiedzieć się, czy źródłem jest ręka, czy kontroler ruchu

    if (interactionSourceState.source.kind == InteractionSourceKind.Hand) {
         // ...
    }
    

Sondowanie pod kątem przewidywanych przesyłania dalej pozycji renderowania

  • Podczas sondowania danych źródłowych interakcji z rąk i kontrolerów, pozy, które otrzymujesz do przodu, są przewidywane przez chwilę w czasie, gdy fotony tej ramki dotrą do oczu użytkownika. Przewidywane do przodu pozy najlepiej nadają się do renderowania kontrolera lub przechowywanego obiektu każdej ramki. Jeśli używasz danej prasy lub wydania z kontrolerem, będzie to najbardziej dokładne, jeśli użyjesz historycznych interfejsów API zdarzeń opisanych poniżej.

    var sourcePose = interactionSourceState.sourcePose;
    Vector3 sourceGripPosition;
    Quaternion sourceGripRotation;
    if ((sourcePose.TryGetPosition(out sourceGripPosition, InteractionSourceNode.Grip)) &&
         (sourcePose.TryGetRotation(out sourceGripRotation, InteractionSourceNode.Grip))) {
         // ...
    }
    
  • Można również uzyskać przewidywaną do przodu pozycję głowy dla tej bieżącej ramki. Podobnie jak w przypadku pozy źródłowej, jest to przydatne do renderowania kursora, chociaż określanie wartości docelowej dla danej prasy lub wydania będzie najdokładniejsze, jeśli użyjesz historycznych interfejsów API zdarzeń opisanych poniżej.

    var headPose = interactionSourceState.headPose;
    var headRay = new Ray(headPose.position, headPose.forward);
    RaycastHit raycastHit;
    if (Physics.Raycast(headPose.position, headPose.forward, out raycastHit, 10)) {
         var cursorPos = raycastHit.point;
         // ...
    }
    

Obsługa zdarzeń źródła interakcji

Aby obsługiwać zdarzenia wejściowe w miarę ich dokładnych danych historycznych, można obsługiwać zdarzenia źródła interakcji zamiast sondowania.

Aby obsłużyć zdarzenia źródła interakcji:

  • Zarejestruj się w celu uzyskania zdarzenia wejściowego InteractionManager . Dla każdego typu zdarzenia interakcji, które Cię interesują, musisz go zasubskrybować.

    InteractionManager.InteractionSourcePressed += InteractionManager_InteractionSourcePressed;
    
  • Obsługa zdarzenia. Po zasubskrybowaniu zdarzenia interakcji wywołanie zwrotne otrzymasz w razie potrzeby. W przykładzie SourcePressed będzie to miało miejsce po wykryciu źródła i przed jego zwolnieniem lub utratą.

    void InteractionManager_InteractionSourceDetected(InteractionSourceDetectedEventArgs args)
         var interactionSourceState = args.state;
    
         // args.state has information about:
            // targeting head ray at the time when the event was triggered
            // whether the source is pressed or not
            // properties like position, velocity, source loss risk
            // source id (which hand id for example) and source kind like hand, voice, controller or other
    }
    

Jak zatrzymać obsługę zdarzenia

Należy zatrzymać obsługę zdarzenia, gdy nie interesuje Cię już zdarzenie lub niszczysz obiekt, który zasubskrybował zdarzenie. Aby zatrzymać obsługę zdarzenia, anuluj subskrypcję zdarzenia.

InteractionManager.InteractionSourcePressed -= InteractionManager_InteractionSourcePressed;

Lista zdarzeń źródłowych interakcji

Dostępne zdarzenia źródła interakcji to:

  • InteractionSourceDetected (źródło staje się aktywne)
  • InteractionSourceLost (staje się nieaktywny)
  • InteractionSourcePressed (naciśnięcie, naciśnięcie przycisku lub wypowiedź "Wybierz")
  • InteractionSourceReleased (koniec naciśnięcia, zwolnienia przycisku lub zakończenia wypowiedzi "Select")
  • InteractionSourceUpdated (przenosi lub zmienia inny stan)

Zdarzenia dotyczące historycznego określania wartości docelowej stanowią, które najdokładniej pasują do prasy lub wydania

Opisane wcześniej interfejsy API sondowania dają aplikacji przewidywaną perspektywę. Chociaż te przewidywane pozy są najlepsze do renderowania kontrolera lub wirtualnego obiektu podręcznego, przyszłe pozy nie są optymalne dla określania wartości docelowej, z dwóch kluczowych powodów:

  • Gdy użytkownik naciśnie przycisk na kontrolerze, może istnieć około 20 ms opóźnienia bezprzewodowego przez Bluetooth, zanim system odbierze naciśnięcie.
  • Następnie, jeśli używasz przewidywanej do przodu pozy, będzie kolejne 10-20 ms przewidywania do przodu zastosowane do czasu, kiedy fotony bieżącej ramki dotrze do oczu użytkownika.

Oznacza to, że sondowanie daje źródłową pozę lub pozę głowy, która jest 30-40 ms do przodu z miejsca, w którym głowa użytkownika i ręce rzeczywiście były z powrotem, gdy doszło do prasy lub wydania. W przypadku wejścia ręcznego urządzenia HoloLens, podczas gdy nie ma opóźnienia transmisji bezprzewodowej, istnieje podobne opóźnienie przetwarzania w celu wykrycia prasy.

Aby dokładnie określić cel na podstawie oryginalnej intencji użytkownika dla naciśnięcia ręki lub kontrolera, należy użyć historycznego pozowania źródła lub pozy głowy z tego zdarzenia wejściowego InteractionSourcePressed lub InteractionSourceReleased .

Możesz wybrać prasę lub wydanie z danymi historycznymi z głowy użytkownika lub kontrolera:

  • Głowa pozuje w momencie, gdy wystąpił gest lub naciśnięcie kontrolera, które może służyć do określania , co użytkownik patrzył na:

    void InteractionManager_InteractionSourcePressed(InteractionSourcePressedEventArgs args) {
         var interactionSourceState = args.state;
         var headPose = interactionSourceState.headPose;
         RaycastHit raycastHit;
         if (Physics.Raycast(headPose.position, headPose.forward, out raycastHit, 10)) {
             var targetObject = raycastHit.collider.gameObject;
             // ...
         }
    }
    
  • Źródło stanowi w momencie, gdy wystąpiło naciśnięcie kontrolera ruchu, które może służyć do określania wartości docelowej , aby określić, na co użytkownik wskazywał kontroler. Będzie to stan kontrolera, który doświadczył prasy. Jeśli renderujesz sam kontroler, możesz zażądać pozowania wskaźnika, a nie pozy uchwytu, aby strzelać ray docelowy z tego, co użytkownik rozważy naturalną końcówkę tego renderowanego kontrolera:

    void InteractionManager_InteractionSourcePressed(InteractionSourcePressedEventArgs args)
    {
         var interactionSourceState = args.state;
         var sourcePose = interactionSourceState.sourcePose;
         Vector3 sourceGripPosition;
         Quaternion sourceGripRotation;
         if ((sourcePose.TryGetPosition(out sourceGripPosition, InteractionSourceNode.Pointer)) &&
             (sourcePose.TryGetRotation(out sourceGripRotation, InteractionSourceNode.Pointer))) {
             RaycastHit raycastHit;
             if (Physics.Raycast(sourceGripPosition, sourceGripRotation * Vector3.forward, out raycastHit, 10)) {
                 var targetObject = raycastHit.collider.gameObject;
                 // ...
             }
         }
    }
    

Przykład procedur obsługi zdarzeń

using UnityEngine.XR.WSA.Input;

void Start()
{
    InteractionManager.InteractionSourceDetected += InteractionManager_InteractionSourceDetected;
    InteractionManager.InteractionSourceLost += InteractionManager_InteractionSourceLost;
    InteractionManager.InteractionSourcePressed += InteractionManager_InteractionSourcePressed;
    InteractionManager.InteractionSourceReleased += InteractionManager_InteractionSourceReleased;
    InteractionManager.InteractionSourceUpdated += InteractionManager_InteractionSourceUpdated;
}

void OnDestroy()
{
    InteractionManager.InteractionSourceDetected -= InteractionManager_InteractionSourceDetected;
    InteractionManager.InteractionSourceLost -= InteractionManager_InteractionSourceLost;
    InteractionManager.InteractionSourcePressed -= InteractionManager_InteractionSourcePressed;
    InteractionManager.InteractionSourceReleased -= InteractionManager_InteractionSourceReleased;
    InteractionManager.InteractionSourceUpdated -= InteractionManager_InteractionSourceUpdated;
}

void InteractionManager_InteractionSourceDetected(InteractionSourceDetectedEventArgs args)
{
    // Source was detected
    // args.state has the current state of the source including id, position, kind, etc.
}

void InteractionManager_InteractionSourceLost(InteractionSourceLostEventArgs state)
{
    // Source was lost. This will be after a SourceDetected event and no other events for this
    // source id will occur until it is Detected again
    // args.state has the current state of the source including id, position, kind, etc.
}

void InteractionManager_InteractionSourcePressed(InteractionSourcePressedEventArgs state)
{
    // Source was pressed. This will be after the source was detected and before it is
    // released or lost
    // args.state has the current state of the source including id, position, kind, etc.
}

void InteractionManager_InteractionSourceReleased(InteractionSourceReleasedEventArgs state)
{
    // Source was released. The source would have been detected and pressed before this point.
    // This event will not fire if the source is lost
    // args.state has the current state of the source including id, position, kind, etc.
}

void InteractionManager_InteractionSourceUpdated(InteractionSourceUpdatedEventArgs state)
{
    // Source was updated. The source would have been detected before this point
    // args.state has the current state of the source including id, position, kind, etc.
}

Kontrolery ruchu w zestawie narzędzi MRTK

Dostęp do gestu i kontrolera ruchu można uzyskać za pomocą Menedżera danych wejściowych.

Postępuj zgodnie z samouczkami

Samouczki krok po kroku, z bardziej szczegółowymi przykładami dostosowywania, są dostępne w akademii Mixed Reality:

MR Input 213 — kontroler ruchu
MR Input 213 — kontroler ruchu

Następny punkt kontrolny programowania

Jeśli śledzisz określoną przez nas podróż dewelopera aparatu Unity, jesteś w trakcie eksplorowania podstawowych bloków konstrukcyjnych zestawu narzędzi MRTK. W tym miejscu możesz przejść do następnego bloku konstrukcyjnego:

Możesz też przejść do Mixed Reality możliwości platformy i interfejsów API:

Zawsze możesz wrócić do punktów kontrolnych tworzenia aparatu Unity w dowolnym momencie.

Zobacz też