Kontrolery ruchu w aucie Unity

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

Aparat Unity zapewnia dwa podstawowe sposoby uzyskiwania dostępu do danych wejściowych przestrzennych dla środowiska 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 środowiska 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 środowiska MR systemu Windows" odnosi 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 środowiska Windows Mixed Reality są zwykle zgodne z identyfikatorami przycisków/osi Oculus.

Mapowania identyfikatorów przycisków/osi dla usługi Windows Mixed Reality różnią się od mapowań oprogramowania 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.
Wkład Typowe interfejsy API aparatu Unity
(Input.GetButton/GetAxis)
Interfejs API danych wejściowych specyficznych dla systemu Windows
(XR. WSA. Dane wejściowe)
Lewej Prawej
Wybierz wciśnięty wyzwalacz 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) Button 15 (gamepad compat) selectPressedAmount > 0.0
Naciśnięcie przycisku menu Przycisk 6* Przycisk 7* menuPressed
Naciśnięty przycisk uchwytu Oś 11 = 1.0 (bez wartości analogowych)
Button 4 (gamepad compat)
Oś 12 = 1.0 (bez wartości analogowych)
Button 5 (gamepad compat)
Uchwycić
Szminka X (po lewej: -1.0, prawa: 1.0) Oś 1 Oś 4 thumbstickPosition.x
Kciuk Y (góra: -1.0, dolna: 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, 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 pozy lub wskaźnik pozy Uchwyt pozuje tylko: XR. InputTracking.GetLocalPosition
XR. InputTracking.GetLocalRotation
Pass Grip lub Pointer 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 biblioteki OpenVR ze względu na kolizje mapowań używanych przez gamepady, Oculus Touch i OpenVR.

OpenXR

Aby dowiedzieć się więcej na temat 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 z danych wejściowych specyficznych dla kontrolera na bardziej uogólnialne Dane wejścioweFeatureUsage, sposób identyfikowania i kategoryzowania dostępnych danych wejściowych XR, odczytywania danych z tych danych wejściowych i nie tylko.

Wtyczka OpenXR rzeczywistości mieszanej udostępnia dodatkowe profile interakcji wejściowych, mapowane na standardowe dane InputFeatureUsage, jak opisano poniżej:

InputFeatureUsage Kontroler HP Reverb G2 (OpenXR) HoloLens Hand (OpenXR)
primary2DAxis Joystick
primary2DAxisClick Przełącznik — kliknięcie
wyzwalacz Wyzwalacz
chwyt Chwyt Naciśnięcie lub wycisnięcie powietrza
primaryButton [X/A] — naciśnij Naciśnij powietrze
secondaryButton [Y/B] - Naciśnij
gripButton Uchwyt — naciskanie
triggerButton Wyzwalacz — naciśnij
menuButton Menu

Pozy uchwytu a punktowanie pozy

Windows Mixed Reality obsługuje kontrolery ruchu w różnych czynnikach formularzy. 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 we współrzędnych globalnych ś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.

W immersyjnych zestawach nagłownych uchwyt najlepiej użyć do renderowania ręki użytkownika lub obiektu trzymanego w ręku użytkownika. Pozy uchwytu są również używane podczas wizualizowania kontrolera ruchu. Model renderowalny dostarczony przez system Windows dla kontrolera ruchu używa uchwytu jako punktu początkowego i środka obrotu.

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

  • Położenie uchwytu: Centroid palmowy w naturalny sposób, skorygowany w lewo lub w prawo, aby wyśrodkować położenie w uchwytie. Na kontrolerze ruchu Windows Mixed Reality to ustawienie zwykle jest wyrównane z przyciskiem Uchwyt.
  • Oś prawej 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 od lewej dłoni, do tyłu od prawej dłoni)
  • przodu orientacji uchwytu: Po zamknięciu ręki częściowo (jakby przytrzymanie kontrolera), ray, który wskazuje "do przodu" przez rurkę utworzoną przez palce non-thumb.
  • Oś uściśnięć 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 Grip).

Pozowanie wskaźnika

Wskaźnik przedstawia wskazówkę kontrolera wskazującą do przodu.

Pozowanie wskaźnika dostarczonego przez system najlepiej nadaje się do emisji raycast podczas renderowania samego modelu kontrolera. Jeśli renderujesz inny obiekt wirtualny zamiast kontrolera, taki jak pistolet wirtualny, należy wskazać promienie najbardziej naturalne dla tego obiektu wirtualnego, takie jak ray, który podróżuje wzdłuż lufy modelu pistoletu zdefiniowanego przez aplikację. Ponieważ użytkownicy widzą 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 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 pozuje 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 elementami można znaleźć w temacie Specyfikacja OpenXR — ścieżki wejściowe.

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

Pozy dostarczane przez InputFeatureUsages PointerPosition, PointerRotation, PointerVelocity i PointerAngularVelocity reprezentują pozy cel 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 XR aparatu Unity — haptics.

Stan śledzenia kontrolera

Podobnie jak zestawy nagłowne, 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 wystarczająco długo, pozycje kontrolera spadną do przybliżonych pozycji dokładności.

W tym momencie system zablokuje kontroler do użytkownika, śledząc pozycję użytkownika podczas poruszania się, jednocześnie ujawniając prawdziwą orientację kontrolera przy użyciu czujników orientacji wewnętrznej. Wiele aplikacji, które używają kontrolerów do wskazywania i aktywowania elementów interfejsu użytkownika, może działać normalnie, a w przybliżonej dokładności bez zauważenia przez 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 ŹródłoLossRisk PositionAccuracy TryGetPosition
Wysoka dokładność < 1.0 Wysoki prawda
Wysoka dokładność (ryzyko utraty) == 1.0 Wysoki prawda
Przybliżona dokładność == 1.0 Przybliżony prawda
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ść: 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 zasłonięty z czujników zestawu słuchawkowego (np. przez drugą rękę użytkownika) będzie nadal zwracać wysoką dokładność 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ć położenia 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.
  • Przybliżona dokładność: gdy kontroler utracił śledzenie wizualne wystarczająco długo, pozycje kontrolera spadną do przybliżonych pozycji dokładności. W tym momencie system zablokuje kontroler do użytkownika, śledząc pozycję użytkownika podczas poruszania się, jednocześnie ujawniając prawdziwą orientację kontrolera przy użyciu czujników orientacji wewnętrznej. Wiele aplikacji, które używają kontrolerów do wskazywania i aktywowania elementów interfejsu użytkownika, może działać normalnie, a w przybliżonej dokładności bez zauważenia przez użytkownika. Aplikacje z cięższymi wymaganiami wejściowymi mogą zdecydować się na 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: 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 zablokowane ciało 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 umieścić kontroler, który następnie został 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 platformy 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 wprowadzania aparatu Unity, powiązania przycisków 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 środowisku Unity i rozwiń właściwości sekcji Prześlij w obszarze Osie. Zmień właściwość Przycisk dodatni lub Alt Positive Button, aby odczytać przycisk ctrl 14, w następujący sposób:

InputManager aparatu Unity
Menedżer danych wejściowych aparatu Unity

Następnie skrypt może sprawdzić 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ż uzyskać dostęp do przycisków ręcznie przy użyciu ich w pełni kwalifikowanej nazwy, używając 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ć przy użyciu XR. InputTracking:

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

Uwaga

Powyższy kod reprezentuje pozę uchwytu kontrolera (gdzie użytkownik posiada kontroler), który jest przydatny do renderowania miecza lub pistoletu w ręku użytkownika lub modelu samego kontrolera.

Relacja między tą uściskiem 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)

Uwaga

Jeśli projekt korzysta z dowolnego Z XR. Interfejsy API usługi WSA, są one stopniowo wycofywane na rzecz zestawu XR SDK 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 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 o wejściowych danych wejściowych systemu Windows Mixed Reality (dla urządzeń HoloLens) i kontrolerach 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, 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 udostępnia informacje, takie jak:

  • Jakiego rodzaju 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 dotykowy

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

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

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

  • Podczas sondowania danych źródła interakcji z rąk i kontrolerów, pozy, które otrzymujesz, są przewidywane przez chwilę w czasie, gdy fotony tej ramki dotrą do oczu użytkownika. Przewidywane do przodu pozy są najlepiej używane 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żywasz 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 pozę 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 najbardziej dokładne, jeśli używasz 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ł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ę interesują, musisz go zasubskrybować.

    InteractionManager.InteractionSourcePressed += InteractionManager_InteractionSourcePressed;
    
  • Obsługa zdarzenia. Po zasubskrybowaniu zdarzenia interakcji otrzymasz wywołanie zwrotne, jeśli jest to konieczne. 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 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ł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 końca wypowiedzi "Wybierz")
  • InteractionSourceUpdated (przenosi lub w inny sposób zmienia jakiś stan)

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

Opisane wcześniej interfejsy API sondowania zapewniają przewidywaną pozycję aplikacji. 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 otrzyma naciśnięcie.
  • Następnie, jeśli używasz przewidywanej pozycji do przodu, będzie kolejne 10–20 ms przewidywania do przodu zastosowane do czasu, w którym fotony bieżącej ramki dotrą 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, chociaż nie ma opóźnienia transmisji bezprzewodowej, istnieje podobne opóźnienie przetwarzania w celu wykrycia prasy.

Aby dokładnie określić cel w oparciu o oryginalną intencję użytkownika dla ręki lub naciśnięcia kontrolera, należy użyć historycznej pozycji źródłowej 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 ich kontrolera:

  • W momencie, gdy wystąpił gest lub naciśnięcie kontrolera, którego można użyć do określania wartości docelowej w celu określenia, 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órego można użyć do określania wartości docelowej w celu określenia, 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ć pozy wskaźnika, a nie uścisku, aby strzelić ray docelowy z tego, co użytkownik rozważy naturalny wierzchołek 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 rzeczywistości mieszanej:

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

Następny punkt kontrolny programowania

Jeśli śledzisz określoną 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 możliwości i interfejsów API platformy rzeczywistości mieszanej:

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

Zobacz też