Kontrolery ruchu w a unity

Istnieją dwa kluczowe sposoby działania na spojrzeniach w aucie Unity: gesty ręczne i kontrolery ruchu w HoloLens i immersyjnego urządzenia HMD. Dostęp do danych dla obu źródeł danych wejściowych przestrzennych uzyskuje się za pośrednictwem tych samych interfejsów API w a aparatu Unity.

Unity zapewnia dwa podstawowe sposoby uzyskiwania dostępu do danych wejściowych przestrzennych na 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 platformy Windows Mixed Reality uwidacznia pełny zestaw przestrzennych danych wejściowych.

Interfejsy API danych wejściowych XR aparatu Unity

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

Więcej informacji na temat interfejsów API XR możnaznaleźć 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 wymienione poniżej za pośrednictwem interfejsów API Input.GetButton/GetAxis. Kolumna "Windows mr-specific" 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 przycisku/osi dla Windows Mixed Reality są zazwyczaj zgodne z identyfikatorami przycisku/osi Oculus.

Mapowania identyfikatorów przycisków/osi Windows Mixed Reality się od mapowań OpenVR na dwa sposoby:

  1. Mapowanie używa identyfikatorów tabletów dotykowych, które różnią się od pazy, do obsługi kontrolerów z zarówno patykami, jak i tabletami dotykowymi.
  2. Mapowanie pozwala uniknąć przeciążania identyfikatorów przycisków A i X dla przycisków Menu, aby pozostawić je dostępne dla fizycznych przycisków ABXY.
Dane wejściowe Typowe interfejsy API aparatu Unity
(Input.GetButton/GetAxis)
Windows Interfejs API danych wejściowych specyficzny dla mr
(XR. WSA. Dane wejściowe)
Lewej Prawej
Wybieranie naciśniętego wyzwalacza Oś 9 = 1,0 Oś 10 = 1,0 wybierz pozycjęPressed
Wybieranie wartości analogicznej wyzwalacza Oś 9 Oś 10 selectPressedAmount
Wybieranie częściowo naciśniętego wyzwalacza Przycisk 14 (gamepad compat) Przycisk 15 (gamepad compat) selectPressedAmount > 0.0
Naciśnięty przycisk Menu Przycisk 6* Przycisk 7* menuPressed
Naciśnięty przycisk Uchwyt Oś 11 = 1,0 (bez wartości analogicznych)
Przycisk 4 (gamepad compat)
Oś 12 = 1,0 (bez wartości analogicznych)
Przycisk 5 (gamepad compat)
Uchwycić
Thumbstick X (po lewej stronie: -1.0, prawa: 1.0) Oś 1 Oś 4 thumbstickPosition.x
Thumbstick Y (top: -1.0, bottom: 1.0) Oś 2 Oś 5 thumbstickPosition.y
Naciśnięta pazma palca Przycisk 8 Przycisk 9 thumbstickPressed
Touchpad X (po lewej stronie: -1.0, prawa: 1.0) Oś 17* Oś 19* touchpadPosition.x
Touchpad Y (górny: -1.0, dół: 1.0) Oś 18* Oś 20* touchpadPosition.y
Dotknieliśmy touchpadu Przycisk 18* Przycisk 19* touchpadTouched
Naciśnięty touchpad Przycisk 16* Przycisk 17* touchpadPressed
6DoF pozy lub pozy wskaźnika Tylko ułożenie: XR. InputTracking.GetLocalPosition
XR. InputTracking.GetLocalRotation
Przekaż wskaźnik 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 aparatu Unity na platformie OpenVR z powodu kolizji mapowań używanych przez gamepady, Oculus Touch i OpenVR.

OpenXR

Aby poznać podstawy interakcji rzeczywistości mieszanej w a unity, odwiedź stronę Podręcznik aparatu Unity dla danych wejściowych XR aparatu Unity. W tej dokumentacji aparatu Unity opisano mapowania danych wejściowych specyficznych dla kontrolera na bardziej uogólnialne dane wejściowe InputFeatureUsage, sposób identyfikacji i kategoryzowania dostępnych danych wejściowych XR, sposobu odczytywania danych z tych danych wejściowych i nie tylko.

Wtyczka OpenXR Mixed Reality dodatkowe profile interakcji danych wejściowych zamapowane na standardowe wtyczki InputFeatureUsage zgodnie z poniższymi informacjami:

InputFeatureUsage Kontroler HP Reverb G2 (OpenXR) HoloLens Hand (OpenXR)
primary2DAxis Joystick
primary2DAxisKliknij Klikanie przycisku
Wyzwalacz Wyzwalacz
Uchwyt Uchwyt Naciśnięcie w powietrzu lub naciśnięcie w powietrzu
primaryButton [X/A] — naciśnij klawisz Naciśnięcie w powietrzu
secondaryButton [Y/B] — naciśnij klawisz
button Grip - Press
triggerButton Wyzwalacz — naciśnij klawisz
menuButton Menu

Pozy a ułożenie punktowe

Windows Mixed Reality obsługuje kontrolery ruchu w różnych kształtach. Projekt każdego kontrolera różni się w relacji między położeniem ręki użytkownika a naturalnym "kierunkiem do przodu", który powinien być przez aplikacje nakierowywny 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 pępka i pozycja wskaźnika. Współrzędne punktu i punktu wskaźnika są wyrażane przez wszystkie interfejsy API aparatu Unity w globalnych współrzędnych świata aparatu Unity.

Pozy

Ułożenie pępka reprezentuje lokalizację pępka użytkowników, wykrytego przez HoloLens lub trzymającego kontroler ruchu.

W przypadku immersywnych zestawów nagłownych pozycja nagłowna najlepiej jest używać do renderowania ręki użytkownika lub obiektu przechowywanego w rękach użytkownika. Ułożenie pępka jest również używane podczas wizualizowania kontrolera ruchu. Model renderowalny dostarczany przez Windows kontrolera ruchu używa pozy uchwytu jako źródła i środka obrotu.

Ułożenie pępka jest zdefiniowane w następujący sposób:

  • Położenie uchwytu: centroida uchwytu podczas trzymania kontrolera w naturalny sposób, dopasowana w lewo lub w prawo w celu wyśrodknięcia pozycji w obrębie uchwytu. Na Windows Mixed Reality ruchu ta pozycja jest zazwyczaj wyrównana z przyciskiem Chwyć.
  • Oś prawa orientacji ręki: gdy całkowicie otworzysz rękę w celu postaci płaskiej ułożenia 5-palca, promienia, które jest normalne dla ręki (do przodu od lewej ryucha, do tyłu od prawego rąbka)
  • do przodu w orientacji poziomej: Gdy zamkniesz rękę częściowo (tak, jakby trzymając kontroler), promienia, który wskazuje "do przodu" przez kętę, która została uformowana przez kciuki nienadmięciowe.
  • w górę orientacji pionowej: oś w górę wynika z definicji prawo i do przodu.

Dostęp do pozy najechania można uzyskać za pośrednictwem wejściowego interfejsu API (XR) aparatu Unity. InputTracking. GetLocalPosition/Rotation Windows ) lub za pośrednictwem interfejsu API specyficznego dla mr (sourceState.sourcePose.TryGetPosition/Rotation) lub za pośrednictwem interfejsu API specyficznego dla mr (sourceState.sourcePose.TryGetPosition/Rotation) z żądaniem pozy danych dla węzła Node (Węzeł).

Pozycja wskaźnika

Pozycja wskaźnika reprezentuje wierzchołek kontrolera w kierunku do przodu.

Pozycja wskaźnika dostarczonego przez system najlepiej jest używana do emisji promieniowej podczas renderowania samego modelu kontrolera. W przypadku renderowania innego obiektu wirtualnego w miejscu kontrolera, takiego jak wirtualny działo, należy wskazać promienie najbardziej naturalne dla tego obiektu wirtualnego, takie jak promienie, które przemieszczają się wzdłuż pochyłek modelu z działem zdefiniowanym przez aplikację. Ponieważ użytkownicy widzą obiekt wirtualny, a nie kontroler fizyczny, nakierowanie go na obiekt wirtualny będzie prawdopodobnie bardziej naturalne dla użytkowników korzystających z aplikacji.

Obecnie Windows pozycja wskaźnika jest dostępna w a unity tylko za pośrednictwem interfejsu API specyficznego dla mr, sourceState.sourcePose.TryGetPosition/Rotation, przekazując jako argument interactionSourceNode.Pointer.

OpenXR

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

  • Ułożenie uchwytu do renderowania obiektów w rękach
  • Celem jest nakierowanie na świat.

Więcej informacji na temat tego projektu i różnic między tymi dwoma pozycjami można znaleźć w specyfikacji OpenXR — input Subpaths ( Specyfikacja OpenXR — ścieżki podrzędne danych wejściowych).

Pozycja zapewniana przez wartości InputFeatureUsages DevicePosition, DeviceRotation, DeviceVelocity i DeviceAngularVelocity reprezentuje ułożenie przepuści OpenXR. Wartości InputFeatureUsage związane z ułożeniem pępka są definiowane w wspólnych usługach aparatuUnity .

Pozycja dostarczana przez inputFeatureUsages PointerPosition, PointerRotation, PointerVelocity i PointerAngularVelocity reprezentuje położenie celu OpenXR. Te wartości InputFeatureUsage nie są zdefiniowane w żadnych dołączonych plikach C#, dlatego należy zdefiniować własne wartości InputFeatureUsage w następujący sposób:

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

Haptics

Aby uzyskać informacje na temat korzystania z haptyki w systemie wejściowym 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 w przypadku zestawów nagłownych kontroler Windows Mixed Reality ruchu nie wymaga konfiguracji zewnętrznych czujników śledzenia. Zamiast tego kontrolery są śledzone przez czujniki w samym zestawie nagłownym.

Jeśli użytkownik przenosi kontrolery poza pole widzenia zestawu nagłownego, Windows w większości przypadków wywnioskuje pozycje kontrolera. Gdy kontroler utraci śledzenie wizualne wystarczająco długo, pozycje kontrolera spadnie do pozycji przybliżonej dokładności.

W tym momencie system zablokuje kontroler użytkownikowi, śledząc jego położenie 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 nakierowania i aktywowania elementów interfejsu użytkownika, może działać normalnie z przybliżoną dokładnością bez zacałowania użytkownika.

Jawne uzasadnienie dotyczące śledzenia stanu

Aplikacje, które chcą traktować pozycje inaczej w zależności od stanu śledzenia, mogą przejść dalej i zbadać 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ść (na 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ą zdefiniowane w następujący sposób:

  • Wysoka dokładność: Kontroler ruchu znajduje się w polu widzenia zestawu nagłownego, ale na ogół zapewnia wysoką dokładność na podstawie śledzenia wizualnego. Ruchomy kontroler, który chwilowo opuszcza pole widzenia lub jest chwilowo zasłaniany przed czujnikami nagłownym (np. przez użytkownika), przez krótki czas będzie nadal zwracać wysoką dokładność, na podstawie śledzenia bezwładności samego kontrolera.
  • Wysoka dokładność (na ryzyko utraty): Gdy użytkownik przesuwa kontroler ruchu za krawędzią pola widoku zestawu nagłownego, zestaw nagłowny wkrótce nie będzie w stanie wizualnie śledzić położenia kontrolera. Aplikacja wie, kiedy kontroler osiągnął tę granicę fov, widzisz, że sourceLossRisk osiągnie 1,0. W tym momencie aplikacja może zdecydować się na wstrzymanie gestów kontrolera, które wymagają stałego strumienia punktów wysokiej jakości.
  • Przybliżona dokładność: Gdy kontroler utraci śledzenie wizualne wystarczająco długo, pozycje kontrolera spadnie do pozycji przybliżonej dokładności. W tym momencie system zablokuje kontroler użytkownikowi, śledząc jego położenie 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 nakierowania i aktywowania elementów interfejsu użytkownika, może działać normalnie z przybliżoną dokładnością bez zacałowania użytkownika. Aplikacje o większych wymaganiach dotyczących danych wejściowych mogą zdecydować się na sprawdzenie tego spadku z Wysoka dokładność do Przybliżona dokładność, kontrolując właściwość PositionAccuracy, na przykład w celu zapewnienia użytkownikowi w tym czasie bardziej przyjaznego miejsca docelowego poza ekranem.
  • Brak pozycji: Kontroler może działać z przybliżoną dokładnością przez długi czas, ale czasami system wie, że nawet pozycja zablokowana treści nie ma w tej chwili znaczenia. Na przykład kontroler, który został włączony, mógł nigdy nie być zaobserwowany wizualnie lub użytkownik może schować kontroler, który zostanie następnie odebrany przez kogoś innego. W takich momentach system nie zapewni żadnej pozycji aplikacji, a pozycja TryGetPosition zwróci wartość false.

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

Przestrzeń nazw: UnityEngine, UnityEngine.XR
Typy: Input, XR. InputTracking

Obecnie aparatu Unity używa ogólnych interfejsów API Input.GetButton/Input.GetAxis do 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 XR SDK, w tym Windows Mixed Reality.

Pobieranie stanu naciśnięcia przycisku logicznego

Aby użyć ogólnych wejściowych interfejsów API aparatu Unity, zwykle zaczniesz od podłączenia przycisków i osi do nazw logicznych w menedżerze danych wejściowych aparatu Unity,wiążąc przycisk lub identyfikatory osi z każdą nazwą. Następnie możesz napisać kod, który odwołuje się do nazwy tego przycisku logicznego/osi.

Aby na przykład zamapować przycisk wyzwalacza lewego kontrolera ruchu na akcję Prześlij, przejdź do sekcji Edit > Project Ustawienia > Input within Unity (Edytowanie danych wejściowych w a aparatu Unity) i rozwiń właściwości sekcji Submit (Prześlij) w obszarze Axes (Osie). Zmień właściwość Przycisk dodatni lub Przycisk alternatywny dodatni, aby odczytać przycisk 14 w ten sposób:

InputManager aparatu Unity
Unity InputManager

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

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

Więcej przycisków logicznych można dodać, zmieniając właściwość Rozmiar w obszarze Osie.

Pobieranie stanu naciśnięcia przycisku fizycznego bezpośrednio

Dostęp do przycisków można również uzyskać ręcznie, używając ich w pełni kwalifikowanej nazwy, używając metody Input.GetKey:

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

Pobieranie ułożenia kontrolera ruchu lub ręki

Dostęp do pozycji 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 pozy pęsku kontrolera (gdzie użytkownik posiada kontroler), co jest przydatne do renderowania piłki lub działa w rękach użytkownika lub modelu samego kontrolera.

Relacja między tym ułożeniem cyzy a ułożeniem wskaźnika (gdzie wskazuje wierzchołek kontrolera) może się różnić między kontrolerami. W tej chwili uzyskiwanie dostępu do wskaźnika kontrolera jest możliwe tylko za pośrednictwem interfejsu API danych wejściowych specyficznego dla mr, opisanego w poniższych sekcjach.

Windows specyficzne dla danego interfejsu API (XR. WSA. Dane wejściowe)

Przestroga

Jeśli projekt używa dowolnego z XR. Interfejsy API WSA są wywłaszczane na rzecz zestawu XR SDK w przyszłych wersjach aparatu Unity. W przypadku nowych projektów zalecamy używanie zestawu XR SDK od początku. Więcej informacji o systemie wejściowym XR i interfejsach 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 danych wejściowych Windows Mixed Reality (dla systemu HoloLens) i kontrolerów ruchu, możesz użyć interfejsów API wejściowych danych przestrzennych specyficznych dla usługi Windows w przestrzeni nazw UnityEngine.XR.WSA.Input. Dzięki temu można uzyskać dostęp do dodatkowych informacji, takich jak dokładność pozycji lub rodzaj źródła, dzięki czemu można odróżnić ręce i kontrolery.

Sondowanie stanu kontrolerów rąk i ruchu

Stan tej ramki można sondowania dla każdego źródła interakcji (kontrolera ruchu lub ręki) przy użyciu metody GetCurrentReading.

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

Każda wartość InteractionSourceState, która zostanie wrócisz, reprezentuje źródło interakcji w bieżącym momencie w czasie. InteractionSourceState uwidacznia informacje, takie jak:

  • Jakiego rodzaju naciśnięcia występują (Select/Menu/Chwyć/Touchpad/Thumbstick)

    if (interactionSourceState.selectPressed) {
         // ...
    }
    
  • Inne dane specyficzne dla kontrolerów ruchu, takie jak współrzędne XY i dotknięcie klawiatury dotykowej i/lub kciuka

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

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

Sondowanie pod celu przewidywania przewidywanych wyników renderowania

  • Podczas sondowania danych źródłowych interakcji z rąk i kontrolerów pozycja, która jest przewidywana do przodu, na moment w czasie, gdy fotony tej ramki dotrą do oczu użytkownika. Do renderowania kontrolera lub przechowywanego obiektu najlepiej wykorzystać ułożenie przewidywane do przodu w każdej ramce. Jeśli dany komunikat ma być przeznaczony dla kontrolera, będzie to najdokładniejsze w przypadku korzystania z 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 ułożenie głowy dla bieżącej ramki. Podobnie jak w przypadku pozy źródłowej, jest to przydatne do renderowania kursora, chociaż nakierowanie na dane naciśnięcie lub wydanie będzie najdokładniejsze, 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ługiwać zdarzenia wejściowe w przypadku ich dokładnych historycznych danych o pozy, można obsługiwać zdarzenia źródła interakcji zamiast sondowania.

Aby obsługiwać zdarzenia źródła interakcji:

  • Zarejestruj się, aby uzyskać zdarzenie wejściowe InteractionManager. Dla każdego typu zdarzenia interakcji, które Cię interesuje, musisz go zasubskrybować.

    InteractionManager.InteractionSourcePressed += InteractionManager_InteractionSourcePressed;
    
  • Obsługa zdarzenia. Po zasubskrybowania zdarzenia interakcji otrzymasz wywołanie zwrotne w razie potrzeby. W przykładzie SourcePressed będzie to możliwe po wykryciu źródła i przed jego zwolnieniu lub utracie.

    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 interesuje Cię już zdarzenie lub niszczenie obiektu, który zasubskrybował zdarzenie. Aby zatrzymać obsługę zdarzenia, anuluj subskrypcję wydarzenia.

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ę nieaktywne)
  • InteractionSourcePressed (naciśnięcie, naciśnięcie przycisku lub wypowiedź "Wybierz")
  • InteractionSourceReleased (koniec naciśnięcia, przycisk został zwolniony lub koniec wypowiedzi "Wybierz")
  • InteractionSourceUpdated (przenosi lub w inny sposób zmienia jakiś stan)

Zdarzenia dla historycznego określania celu, które najdokładniej pasują do informacji o naciśnięciu lub wydaniu

Opisane wcześniej interfejsy API sondowania zapewniają aplikacji przewidywaną do przodu postawę. Chociaż te przewidywane pozy są najlepsze do renderowania kontrolera lub wirtualnego obiektu pętowego, 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 być około 20 ms opóźnienia sieci bezprzewodowej przez Bluetooth, zanim system odbierze naciśnięcie.
  • Następnie, jeśli używasz pozycji przewidywanej do przodu, zastosowanoby kolejne 10–20 ms przewidywania do przodu, aby osiągnąć czas, w którym fotony bieżącej ramki dotrą do oczu użytkownika.

Oznacza to, że sondowanie zapewnia ułożenie źródła lub głowy o 30–40 ms do przodu, z którego rzeczywiście wrócili z ręki i głowy użytkownika w momencie naciśnięcia lub wydania. W HoloLens ręcznego, chociaż nie ma opóźnienia transmisji bezprzewodowej, istnieje podobne opóźnienie przetwarzania do wykrywania naciśnięcia.

Aby dokładnie określić cel w oparciu o pierwotną intencję użytkownika dla naciśnięcia ręki lub kontrolera, należy użyć historycznej pozy źródłowej lub ułożenia głowy z tego zdarzenia wejściowego InteractionSourcePressed lub InteractionSourceReleased.

Można wybrać wersję docelową z historycznymi danymi o pozy od głowy użytkownika lub jego kontrolera:

  • Ułożenie głowy 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, na co użytkownik patrzył:

    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órego można użyć do określania wartości docelowej w celu określenia, na co użytkownik kierował kontroler. Będzie to stan kontrolera, na którym wystąpiło naciśnięcie klawisza . Jeśli renderowany jest sam kontroler, możesz zażądać ułożenia wskaźnika, a nie pozy pępka, aby wywrzeć promienia docelowego z tego, co użytkownik będzie uwzględniać w naturalnej wierzchołku 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 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 mrTK

Dostęp do gestu i kontrolera ruchu można uzyskać z wejściowego menedżera.

Postępuj zgodnie z samouczkami

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

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

Następny punkt kontrolny rozwoju

Jeśli podążasz za rozplanową podróżą po programie Unity, jesteś w trakcie eksplorowania podstawowych bloków konstrukcyjnych mrTK. W tym miejscu możesz przejść do następnego bloku:

Lub przejdź do Mixed Reality platformy i interfejsów API:

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

Zobacz też