Kontrolery ruchu w środowisku Unity

Istnieją dwa kluczowe sposoby podejmowania działań na spojrzenie w środowisku Unity, gesty dłoni i kontrolery ruchu w 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 środowisku 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 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 odpowiadają identyfikatorom przycisku/osi Oculus.

Mapowania identyfikatorów przycisków/osi dla Windows Mixed Reality różnią się od mapowań 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 szminkami, jak i touchpadami.
  2. Mapowanie pozwala uniknąć przeciążenia identyfikatorów przycisków A i X dla 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 zestawu narzędzi mr systemu Windows
(XR. WSA. Dane wejściowe)
Lewej Prawej
Wybierz wyzwalacz naciśnięty 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 (kompat gamepad) Przycisk 15 (kompat gamepad) 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 (kompat gamepad)
Oś 12 = 1.0 (bez wartości analogowych)
Przycisk 5 (kompat gamepad)
Uchwycić
Kciuk X (po lewej: -1.0, prawy: 1.0) Oś 1 Oś 4 kciukPosition.x
Kciuk Y (górny: -1.0, dolny: 1.0) Oś 2 Oś 5 thumbstickPosition.y
Naciśnięty kciuk Przycisk 8 Przycisk 9 kciukPressed
Touchpad X (po lewej: -1.0, po prawej: 1.0) Oś 17* Oś 19* touchpadPosition.x
Touchpad Y (górna: -1.0, dolna: 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 uścisku pozowanie lub wskaźnik Uchwyt pozuje tylko: XR. InputTracking.GetLocalPosition
XR. InputTracking.GetLocalRotation
Przekaż chwyt lub wskaźnik jako argument: sourceState.sourcePose.TryGetPosition
sourceState.sourcePose.TryGetRotation
Stan śledzenia Dokładność pozycji 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 platformy OpenVR z powodu kolizji w mapowaniach używanych przez gamepady, Oculus Touch i OpenVR.

OpenXR

Aby poznać podstawy interakcji rzeczywistości mieszanej w środowisku Unity, odwiedź stronę Podręcznik aparatu Unity dla danych wejściowych XR aparatu Unity. Ta dokumentacja aparatu Unity obejmuje mapowania danych wejściowych specyficznych dla kontrolera na bardziej uogólnialne dane wejściowe InputFeatureUsages, sposób identyfikowania i 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 dane WejścioweFeatureUsagezgodnie z poniższym opisem:

InputFeatureUsage Kontroler HP Reverb G2 (OpenXR) HoloLens Hand (OpenXR)
primary2DAxis Joystick
primary2DAxisClick Przełącznik — kliknij
Wyzwalacz Wyzwalacz
Uchwyt Uchwyt 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

Pozy uchwytu a punktowanie pozy

Windows Mixed Reality obsługuje kontrolery ruchu w różnych czynnikach form. Projekt każdego kontrolera różni się w zależności od położenia 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, pozy uchwytu i pozy 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 w globalnych współrzędnych świata aparatu Unity.

Pozy uchwytu

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

Na immersywnych zestawach słuchawkowych chwyt jest najlepiej używany do renderowania dłoni użytkownika lub obiektu trzymanego w ręku użytkownika. Pozy uchwytu są również używane podczas wizualizowania kontrolera ruchu. Model renderowalny dostarczany przez system Windows dla kontrolera ruchu używa uchwytu, który stanowi źródło i środek rotacji.

Pozy uchwytu są definiowane w następujący sposób:

  • Położenie uchwytu: centroid palmowy podczas trzymania kontrolera naturalnie, wyrównany w lewo lub w prawo, aby wyśrodkować położenie w uścisku. Na kontrolerze ruchu Windows Mixed Reality to położenie jest zwykle wyrównane z przyciskiem Uchwyt.
  • Oś prawej orientacji uchwytu: Kiedy całkowicie otworzysz rękę, aby utworzyć płaską pozę 5-palcem, promienie, które są normalne dla dłoni (do przodu z lewej dłoni, do tyłu z prawej dłoni)
  • Oś przodu orientacji uchwytu: Po zamknięciu ręki częściowo (jakby trzymał kontroler), promieni, który wskazuje "do przodu" przez rurkę utworzoną przez palce nie-kciuka.
  • Oś uścisku w górę: oś w górę dorozumiana przez definicje Prawa i Przodu.

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

Pozowanie wskaźnika

Wskaźnik stanowi końcówkę kontrolera wskazującego do przodu.

W przypadku renderowania samego modelu kontrolera najlepiej używać wskaźnika dostarczonego przez system. Jeśli renderujesz inny obiekt wirtualny zamiast kontrolera, taki jak pistolet wirtualny, należy wskazać ray, który jest najbardziej naturalny dla tego wirtualnego obiektu, takiego 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, wskazanie obiektu wirtualnego prawdopodobnie będzie bardziej naturalne dla użytkowników korzystających z aplikacji.

Obecnie pozycja wskaźnika jest dostępna w środowisku 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 dwoma pozycjami można znaleźć w temacie Specyfikacja OpenXR — ścieżki podrzędne wejściowe.

Pozuje dostarczone przez inputFeatureUsages DevicePosition, DeviceRotation, DeviceVelocity i DeviceAngularVelocity wszystkie reprezentują pozy uchwytu OpenXR. InputFeatureUsages związane z pozami uchwytu są zdefiniowane w CommonUsages aparatu Unity.

Poses dostarczone przez inputFeatureUsages PointerPosition, PointerRotation, PointerVelocity i PointerAngularVelocity wszystkie reprezentują pozy cel OpenXR. Te dane 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 temacie Unity Manual for Unity XR Input - Haptics (Podręcznik aparatu Unity dla danych wejściowych XR aparatu Unity — 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 słuchawkowego, system Windows w większości przypadków kontynuuje wnioskowanie pozycji kontrolera. 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ść użytkownika, śledząc pozycję użytkownika podczas poruszania się, jednocześnie ujawniając prawdziwą orientację kontrolera przy użyciu wewnętrznych czujników orientacji. Wiele aplikacji korzystających z kontrolerów do wskazywania i aktywowania elementów interfejsu użytkownika może działać normalnie, jednocześnie w przybliżonej dokładności bez notowania użytkownika.

Jawne rozumowanie dotyczące stanu śledzenia

Aplikacje, które chcą traktować pozycje inaczej na podstawie stanu śledzenia, mogą przejść 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żone true
Brak pozycji == 1.0 Przybliżone fałsz

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

  • Wysoka dokładność: Podczas gdy kontroler ruchu znajduje się w polu widoku zestawu słuchawkowego, zazwyczaj zapewnia wysoką dokładność pozycji na podstawie śledzenia wizualnego. Ruchomy kontroler, który chwilowo opuszcza pole widoku lub jest chwilowo zaciemniany z czujników zestawu słuchawkowego (np. przez drugą rękę użytkownika) będzie nadal zwracać wysoką dokładność pozy przez krótki czas, na podstawie inertyjnego śledzenia samego kontrolera.
  • Wysoka dokładność (ryzyko utraty): Gdy użytkownik przenosi kontroler ruchu obok krawędzi pola widoku zestawu słuchawkowego, zestaw słuchawkowy wkrótce nie będzie mógł wizualnie śledzić pozycji kontrolera. Aplikacja wie, kiedy kontroler osiągnął tę granicę FOV, widząc ŹródłoLossRisk 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 pozy.
  • 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ść użytkownika, śledząc pozycję użytkownika podczas poruszania się, 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ć o tym spadku 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: Podczas gdy kontroler może działać z przybliżoną dokładnością przez długi czas, czasami system wie, że nawet położenie zablokowanego ciała 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, aby uwidocznić dane wejściowe 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 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 danych wejściowych aparatu Unity, zazwyczaj zaczniesz od podłączania przycisków i osi do nazw logicznych w menedżerze danych wejściowych aparatu Unity, powiązania identyfikatorów przycisku lub 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 środowisku Unity i rozwiń właściwości sekcji Prześlij w obszarze Osie. Zmień właściwość Przycisk dodatni lub Przycisk alternatywny na przycisk dodatni , aby odczytać przycisk 14, w następujący sposób:

InputManager aparatu Unity
Unity InputManager

Następnie skrypt może sprawdzić akcję Prześlij przy użyciu elementu 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ż uzyskać dostęp do przycisków ręcznie przy użyciu 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 pozycji i rotacji kontrolera można uzyskać przy użyciu XR. InputTracking:

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

Uwaga

Powyższy kod reprezentuje postawę 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 tą postawą uchwytu a punktem wskaźnika (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 usługi WSA są one wycofywane na rzecz zestawu SDK XR w przyszłych wersjach aparatu Unity. W przypadku nowych projektów zalecamy użycie zestawu SDK XR od początku. Więcej informacji na temat systemu danych wejściowych I interfejsów API XR 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 danych wejściowych Windows Mixed Reality ręcznych (dla urządzeń HoloLens) i kontrolerów ruchu, możesz użyć interfejsów API wejściowych 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, co pozwala powiedzieć ręce i kontrolery od siebie.

Sondowanie stanu rąk i kontrolerów ruchu

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

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

Każda funkcja InteractionSourceState , którą 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 współrzędne XY i/lub szminki kciuka i stan dotykany

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

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

Sondowanie pod kątem przewidywanych do przodu pozy renderowania

  • Podczas sondowania danych źródłowych interakcji z rąk i kontrolerów pozy, które otrzymujesz, są przewidywane przez chwilę w czasie, gdy zdjęcia tej ramki dotrą do oczu użytkownika. Do renderowania kontrolera lub obiektu przechowywanego każda ramka najlepiej używać przewidywanych do przodu. Jeśli używasz danej prasy lub wydania z kontrolerem, będzie to najbardziej dokładne, jeśli używasz interfejsów API zdarzeń historycznych 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 pozę głowy dla tej bieżącej ramki. Podobnie jak w przypadku pozy źródłowej, jest to przydatne do renderowania kursora, chociaż kierowanie do danej prasy lub wydania będzie najbardziej dokładne, jeśli używasz interfejsów API zdarzeń historycznych 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łużyć 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ę interesuje, musisz go zasubskrybować.

    InteractionManager.InteractionSourcePressed += InteractionManager_InteractionSourcePressed;
    
  • Obsługa zdarzenia. Po zasubskrybowaniu zdarzenia interakcji otrzymasz wywołanie zwrotne 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

Musisz zatrzymać obsługę zdarzenia, gdy nie jesteś już zainteresowany zdarzeniem lub niszczysz obiekt, który zasubskrybował zdarzenie. Aby zatrzymać obsługę zdarzenia, anuluj subskrypcję zdarzenia.

InteractionManager.InteractionSourcePressed -= InteractionManager_InteractionSourcePressed;

Lista zdarzeń źródła 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 wypowiedzi "Wybierz")
  • InteractionSourceReleased (koniec naciśnięcia, przycisku wydanego lub końca wypowiedzi "Wybierz")
  • InteractionSourceUpdated (przenosi lub w inny sposób zmienia jakiś stan)

Zdarzenia dotyczące kierowania historycznego stanowią, że najdokładniej pasuje do prasy lub wydania

Interfejsy API sondowania opisane wcześniej dają przewidywaną przez aplikację postawę do przodu. Podczas gdy przewidywane postawy są najlepsze do renderowania kontrolera lub wirtualnego obiektu ręcznego, przyszłe pozy nie są optymalne dla określania wartości docelowej, z dwóch kluczowych powodów:

  • Gdy użytkownik naciska przycisk na kontrolerze, może istnieć około 20 ms opóźnienia bezprzewodowego przez Bluetooth, zanim system otrzyma naciśnięcie klawisza .
  • Następnie, jeśli używasz przewidywanej pozycji do przodu, będzie kolejne 10–20 ms przewidywania do przodu zastosowane do celu czasu, gdy fotony bieżącej ramki osiągną oczy użytkownika.

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

Aby dokładnie kierować się na podstawie oryginalnej intencji użytkownika dla prasy ręcznej lub kontrolera, należy użyć historycznej pozycji źródłowej lub pozy głowy z tego zdarzenia wejściowego InteractionSourcePressed lub InteractionSourceReleased .

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

  • Pozowanie głowy w momencie wystąpienia gestu lub naciśnięcia kontrolera, który 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 wystąpienia naciśnięcia kontrolera ruchu, które może służyć do określania , na co użytkownik wskazywał kontroler. Będzie to stan kontrolera, który doświadczył prasy. Jeśli renderujesz sam kontroler, możesz poprosić o pozowanie wskaźnika zamiast uścisku, aby strzelić do promienia docelowego 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ć z Poziomu 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:

Wejście MR 213 — kontroler ruchu
Wejście MR 213 — kontroler ruchu

Następny punkt kontrolny programowania

Jeśli obserwujesz określoną przez nas podróż do opracowywania aparatu Unity, jesteś w środku 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 programowania aparatu Unity w dowolnym momencie.

Zobacz też