Bewegungscontroller in Unity

Es gibt zwei wichtige Möglichkeiten, um in Unity auf Ihren Blick zu wirken: Handgesten und Bewegungscontroller in HoloLens und Immersive HMD. Sie greifen auf die Daten für beide Quellen räumlicher Eingaben über die gleichen APIs in Unity zu.

Unity bietet zwei primäre Möglichkeiten für den Zugriff auf räumliche Eingabedaten für Windows Mixed Reality. Die allgemeinen Input.GetButton/Input.GetAxis-APIs funktionieren über mehrere Unity XR SDKs hinweg, während die interactionManager/GestureRecognizer-API für Windows Mixed Reality den vollständigen Satz räumlicher Eingabedaten verfügbar macht.

Unity XR-Eingabe-APIs

Für neue Projekte wird empfohlen, die neuen XR-Eingabe-APIs von Anfang an zu verwenden.

Weitere Informationen zu den XR-APIs finden Sie hier.

Unity-Schaltflächen-/Achsenzuordnungstabelle

Der Eingabe-Manager von Unity für Windows Mixed Reality Motion Controller unterstützt die unten aufgeführten Schaltflächen- und Achsen-IDs über die Input.GetButton/GetAxis-APIs. Die Spalte "Windows MR-specific" verweist auf Eigenschaften, die vom InteractionSourceState-Typ aus verfügbar sind. Jede dieser APIs wird in den folgenden Abschnitten ausführlich beschrieben.

Die Schaltflächen-/Achsen-ID-Zuordnungen für Windows Mixed Reality in der Regel mit den Oculus-Schaltflächen-/Achsen-IDs übereinstimmen.

Die Schaltflächen-/Achsen-ID-Zuordnungen für Windows Mixed Reality unterscheiden sich auf zwei Arten von den Zuordnungen von OpenVR:

  1. Die Zuordnung verwendet Touchpad-IDs, die sich vom Fingerabdruck unterscheiden, um Controller mit Fingerabdrucksticks und Touchpads zu unterstützen.
  2. Die Zuordnung vermeidet eine Überladung der A- und X-Schaltflächen-IDs für die Menüschaltflächen, damit sie für die physischen ABXY-Schaltflächen verfügbar bleiben.
EingabeAllgemeine Unity-APIs
(Input.GetButton/GetAxis)
Windows MR-spezifische Eingabe-API
(XR. WSA. Eingabe)
Linken Rechte Hand
Trigger gedrückt auswählen Achse 9 = 1,0 Achse 10 = 1,0 selectPressed
Trigger-Analogwert auswählen Achse 9 Achse 10 selectPressedAmount
Trigger teilweise gedrückt auswählen Schaltfläche 14 (Gamepad compat) Schaltfläche 15 (Gamepad compat) selectPressedAmount > 0.0
Menüschaltfläche gedrückt Schaltfläche 6* Schaltfläche 7* menuPressed
Grifftaste gedrückt Achse 11 = 1,0 (keine analogen Werte)
Schaltfläche 4 (Gamepad compat)
Achse 12 = 1,0 (keine analogen Werte)
Schaltfläche 5 (Gamepad compat)
Begriffen
Thumbstick X (links: -1.0, rechts: 1.0) Achse 1 Achse 4 thumbstickPosition.x
Thumbstick Y (oben: -1,0, unten: 1,0) Achse 2 Achse 5 thumbstickPosition.y
Fingerabdruckstick gedrückt Schaltfläche 8 Schaltfläche 9 thumbstickPressed
Touchpad X (links: -1.0, rechts: 1.0) Achse 17* Achse 19* touchpadPosition.x
Touchpad Y (oben: -1,0, unten: 1,0) Achse 18* Achse 20* touchpadPosition.y
Touchpad touched Schaltfläche 18* Schaltfläche 19* touchpadTouched
Touchpad gedrückt Schaltfläche 16* Schaltfläche 17* touchpadPressed
6DoF-Griffpose oder Zeigerpose Nur Griffhaltung : XR. InputTracking.GetLocalPosition
XR. InputTracking.GetLocalRotation
Übergeben Sie Grip oder Zeiger als Argument: sourceState.sourcePose.TryGetPosition
sourceState.sourcePose.TryGetRotation
Nachverfolgungsstatus Positionsgenauigkeit und Quellverlustrisiko nur über mr-spezifische API verfügbar sourceState.sourcePose.positionAccuracy
sourceState.properties.sourceLossRisk

Hinweis

Diese Schaltflächen-/Achsen-IDs unterscheiden sich von den IDs, die Unity für OpenVR verwendet, aufgrund von Kollisionen in den Zuordnungen, die von Gamepads, Oculus Touch und OpenVR verwendet werden.

OpenXR

Informationen zu Mixed Reality-Interaktionen in Unity finden Sie im Unity-Handbuch für Unity XR Input. In dieser Unity-Dokumentation werden die Zuordnungen von controllerspezifischen Eingaben zu generalisierbaren InputFeatureUsages behandelt, wie verfügbare XR-Eingaben identifiziert und kategorisiert werden können, wie Daten aus diesen Eingaben gelesen werden können und vieles mehr.

Das Mixed Reality OpenXR-Plug-In bietet zusätzliche Eingabeinteraktionsprofile, die den Standardmäßigen InputFeatureUsageszugeordnet sind, wie unten beschrieben:

InputFeatureUsage HP Reverb G2 Controller (OpenXR) HoloLens Hand (OpenXR)
primary2DAxis Joystick
primary2DAxisClick Joystick – Klicken
Trigger (trigger) Trigger
Griff Griff Luft tippen oder drücken
primaryButton [X/A] – Drücken In die Luft tippen
secondaryButton [Y/B] - Presse
gripButton Griff – Drücken
triggerButton Trigger – Drücken
menuButton Menü

Grip-Pose vs. Pointing Pose

Windows Mixed Reality unterstützt Motion Controller in einer Vielzahl von Formfaktoren. Der Entwurf jedes Controllers unterscheidet sich in seiner Beziehung zwischen der Handposition des Benutzers und der natürlichen Vorwärtsrichtung, die Apps beim Rendern des Controllers verwenden sollten.

Um diese Controller besser darzustellen, gibt es zwei Arten von Posen, die Sie für jede Interaktionsquelle untersuchen können: die Griffposition und die Zeigerhaltung. Sowohl die Koordinaten der Halteposition als auch der Zeigerposition werden von allen Unity-APIs in globalen Unity-Weltkoordinaten ausgedrückt.

Halteposition

Die Griffposition stellt die Position der Handfläche des Benutzers dar, die entweder von einer HoloLens erkannt wird oder einen Bewegungscontroller hält.

Bei immersiven Headsets wird die Griffhaltung am besten verwendet, um die Hand des Benutzers oder ein Objekt in der Hand des Benutzers zu rendern. Die Griffhaltung wird auch bei der Visualisierung eines Bewegungscontrollers verwendet. Das renderbare Modell , das von Windows für einen Bewegungscontroller bereitgestellt wird, verwendet die Griffposition als Ursprung und Mittelpunkt der Drehung.

Die Griffhaltung wird spezifisch wie folgt definiert:

  • Die Griffposition: Der Palmenschwerpunkt beim natürlichen Halten des Controllers, eingestellt links oder rechts, um die Position innerhalb des Griffs zu zentrieren. Auf dem Windows Mixed Reality Motion Controller wird diese Position in der Regel an der Taste "Greifen" ausgerichtet.
  • Die rechte Achse der Griffausrichtung: Wenn Sie Ihre Hand vollständig öffnen, um eine flache 5-Finger-Pose zu bilden, der Strahl, der für Ihre Handfläche normal ist (vorwärts von der linken Handfläche, rückwärts von der rechten Handfläche)
  • Die Vorwärtsachse des Griffs: Wenn Sie Ihre Hand teilweise schließen (als ob Sie den Controller halten), der Strahl, der "vorwärts" durch die Röhre zeigt, die von Ihren Fingern ohne Daumen gebildet wird.
  • Die Nach oben-Achse der Griffausrichtung: Die Nach-oben-Achse, die von den Definitionen Rechts und Vorwärts impliziert wird.

Sie können über die anbieterübergreifende Eingabe-API (XR) von Unity auf die Griffposition zugreifen. InputTracking. GetLocalPosition/Rotation) oder über die Windows MR-spezifische API (sourceState.sourcePose.TryGetPosition/Rotation, die Posendaten für den Grip-Knoten anfordert).

Zeigerhaltung

Die Zeigerposition stellt die Spitze des Controllers dar, der nach vorne zeigt.

Die vom System bereitgestellte Zeigerposition wird am besten zum Raycast verwendet, wenn Sie das Controllermodell selbst rendern. Wenn Sie ein anderes virtuelles Objekt anstelle des Controllers rendern, z. B. eine virtuelle Pistole, sollten Sie mit einem Strahl zeigen, der für dieses virtuelle Objekt am natürlichsten ist, z. B. ein Strahl, der sich entlang des Laufs des app-definierten Waffenmodells bewegt. Da Benutzer das virtuelle Objekt und nicht den physischen Controller sehen können, ist das Zeigen mit dem virtuellen Objekt wahrscheinlich natürlicher für diejenigen, die Ihre App verwenden.

Derzeit ist die Zeigerposition in Unity nur über die Windows MR-spezifische API sourceState.sourcePose.TryGetPosition/Rotation verfügbar, wobei InteractionSourceNode.Pointer als Argument übergeben wird.

OpenXR

Sie haben Zugriff auf zwei Sätze von Posen über OpenXR-Eingabeinteraktionen:

  • Die Griffhaltungen zum Rendern von Objekten in der Hand
  • Das Ziel ist, in die Welt zu zeigen.

Weitere Informationen zu diesem Entwurf und den Unterschieden zwischen den beiden Posen finden Sie in der OpenXR-Spezifikation – Eingabeunterpfade.

Posen, die von inputFeatureUsages DevicePosition, DeviceRotation, DeviceVelocity und DeviceAngularVelocity bereitgestellt werden, stellen alle die OpenXR-Griffposition dar. InputFeatureUsages im Zusammenhang mit Griffhaltungen werden in Den CommonUsages von Unity definiert.

Posen, die von inputFeatureUsages bereitgestellt werden: PointerPosition, PointerRotation, PointerVelocity und PointerAngularVelocity stellen alle die OpenXR-Zielposition dar. Diese InputFeatureUsages sind in keinen enthaltenen C#-Dateien definiert, sodass Sie Ihre eigenen InputFeatureUsages wie folgt definieren müssen:

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

Haptik

Informationen zur Verwendung von Haptik im XR-Eingabesystem von Unity finden Sie in der Dokumentation unter Unity Manual for Unity XR Input – Haptics( Unity Manual for Unity XR Input – Haptics).

Controllernachverfolgungsstatus

Wie die Headsets erfordert auch der Windows Mixed Reality Motion Controller keine Einrichtung externer Tracking-Sensoren. Stattdessen werden die Controller von Sensoren im Headset selbst nachverfolgt.

Wenn der Benutzer die Controller aus dem Sichtfeld des Headsets verschiebt, leitet Windows in den meisten Fällen weiterhin Controllerpositionen ab. Wenn der Controller die visuelle Nachverfolgung lange genug verloren hat, werden die Positionen des Controllers auf ungefähre Genauigkeitspositionen sinken.

An diesem Punkt sperrt das System den Controller für den Benutzer, verfolgt die Position des Benutzers, während er sich bewegt, während er sich bewegt, während er die tatsächliche Ausrichtung des Controllers mithilfe seiner internen Ausrichtungssensoren verfügbar macht. Viele Apps, die Controller verwenden, um auf UI-Elemente zu zeigen und diese zu aktivieren, können normal und in ungefährer Genauigkeit funktionieren, ohne dass der Benutzer dies zu beachten hat.

Überlegungen zur expliziten Nachverfolgung des Zustands

Apps, die Positionen basierend auf dem Nachverfolgungsstatus unterschiedlich behandeln möchten, können weiter gehen und Eigenschaften für den Status des Controllers untersuchen, z. B. SourceLossRisk und PositionAccuracy:

Nachverfolgungsstatus SourceLossRisk PositionAccuracy TryGetPosition
Hohe Genauigkeit < 1.0 High true
Hohe Genauigkeit (bei Verlustgefahr) == 1.0 High true
Ungefähre Genauigkeit == 1.0 Ungefähr true
Keine Position == 1.0 Ungefähr false

Diese Bewegungscontroller-Nachverfolgungszustände werden wie folgt definiert:

  • Hohe Genauigkeit: Während sich der Motion Controller im Sichtfeld des Headsets befindet, bietet er in der Regel positionen mit hoher Genauigkeit, basierend auf visueller Verfolgung. Ein sich bewegender Controller, der vorübergehend das Sichtfeld verlässt oder vorübergehend von den Headset-Sensoren verdeckt wird (z. B. durch die andere Hand des Benutzers), gibt weiterhin für kurze Zeit hochgenaue Posen zurück, basierend auf der Trägheitsnachverfolgung des Controllers selbst.
  • Hohe Genauigkeit (bei Verlustgefahr): Wenn der Benutzer den Motion Controller über den Rand des Sichtfelds des Headsets verschiebt, kann das Headset die Position des Controllers bald nicht mehr visuell nachverfolgen. Die App weiß, wann der Controller diese FOV-Grenze erreicht hat, indem sie sieht, dass SourceLossRisk 1.0 erreicht. An diesem Punkt kann die App Controllergesten anhalten, die einen stetigen Stream von qualitativ hochwertigen Posen erfordern.
  • Ungefähre Genauigkeit: Wenn der Controller die visuelle Nachverfolgung lange genug verloren hat, werden die Positionen des Controllers auf ungefähre Genauigkeitspositionen sinken. An diesem Punkt sperrt das System den Controller für den Benutzer, verfolgt die Position des Benutzers, während er sich bewegt, während er sich bewegt, während er die tatsächliche Ausrichtung des Controllers mithilfe seiner internen Ausrichtungssensoren verfügbar macht. Viele Apps, die Controller verwenden, um auf UI-Elemente zu zeigen und sie zu aktivieren, können wie gewohnt und in ungefährer Genauigkeit funktionieren, ohne dass der Benutzer dies beachten muss. Apps mit höheren Eingabeanforderungen können diesen Rückgang von Hoher Genauigkeit auf Ungefähre Genauigkeit erkennen, indem sie die PositionAccuracy-Eigenschaft untersuchen, um dem Benutzer während dieser Zeit beispielsweise eine großzügigere Trefferbox auf Off-Screen-Zielen zu geben.
  • Keine Position: Während der Controller lange Zeit mit ungefährer Genauigkeit arbeiten kann, weiß das System manchmal, dass selbst eine körperverriegelte Position im Moment nicht sinnvoll ist. Beispielsweise wurde ein aktivierter Controller möglicherweise nie visuell beobachtet, oder ein Benutzer legt einen Controller ab, der dann von einer anderen Person aufgenommen wird. Zu diesem Zeitpunkt stellt das System keine Position für die App bereit, und TryGetPosition gibt false zurück.

Allgemeine Unity-APIs (Input.GetButton/GetAxis)

Namespace:UnityEngine, UnityEngine.XR
Typen: Eingabe, XR. InputTracking

Unity verwendet derzeit seine allgemeinen Input.GetButton/Input.GetAxis-APIs, um Eingaben für das Oculus SDK, das OpenVR SDK und Windows Mixed Reality verfügbar zu machen, einschließlich Hands- und Motion-Controllern. Wenn Ihre App diese APIs für die Eingabe verwendet, kann sie problemlos Motion-Controller für mehrere XR-SDKs unterstützen, einschließlich Windows Mixed Reality.

Abrufen des gedrückten Zustands einer logischen Schaltfläche

Um die allgemeinen Unity-Eingabe-APIs zu verwenden, beginnen Sie in der Regel damit, Schaltflächen und Achsen im Unity-Eingabe-Manager mit logischen Namen zu verknüpfen und eine Schaltfläche oder Achsen-IDs an jeden Namen zu binden. Anschließend können Sie Code schreiben, der sich auf den Namen der logischen Schaltfläche bzw. Achse bezieht.

Wenn Sie z. B. die Triggerschaltfläche des linken Bewegungscontrollers der Aktion Senden zuordnen möchten, wechseln Sie in Unity zu Projekteinstellungseingabe > bearbeiten>, und erweitern Sie die Eigenschaften des Abschnitts Übermitteln unter Achsen. Ändern Sie die Eigenschaft Positive Schaltfläche oder Alt Positive Schaltfläche , um joystick button 14 zu lesen, wie folgt:

InputManager von Unity
Unity InputManager

Ihr Skript kann dann mithilfe von Input.GetButton nach der Submit-Aktion suchen:

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

Sie können weitere logische Schaltflächen hinzufügen, indem Sie die Eigenschaft Größe unter Axes ändern.

Direktes Abrufen des gedrückten Zustands einer physischen Schaltfläche

Sie können mithilfe von Input.GetKey auch manuell über den vollqualifizierten Namen auf Schaltflächen zugreifen:

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

Abrufen der Position eines Hand- oder Bewegungscontrollers

Sie können mithilfe von XR auf die Position und Drehung des Controllers zugreifen . InputTracking:

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

Hinweis

Der obige Code stellt die Griffposition des Controllers dar (in der der Benutzer den Controller hält), die nützlich ist, um ein Schwert oder eine Pistole in der Hand des Benutzers oder ein Modell des Controllers selbst zu rendern.

Die Beziehung zwischen dieser Griffposition und der Zeigerposition (bei der die Spitze des Controllers zeigt) kann sich zwischen controllern unterscheiden. Derzeit ist der Zugriff auf die Zeigerposition des Controllers nur über die MR-spezifische Eingabe-API möglich, die in den folgenden Abschnitten beschrieben wird.

Windows-spezifische APIs (XR. WSA. Eingabe)

Achtung

Wenn Ihr Projekt eine der XR verwendet. WSA-APIs, diese werden in zukünftigen Unity-Releases schrittweise zugunsten des XR SDK eingestellt. Für neue Projekte wird empfohlen, das XR SDK von Anfang an zu verwenden. Weitere Informationen zum XR-Eingabesystem und zu den APIs finden Sie hier.

Namespace:UnityEngine.XR.WSA.Input
Types: InteractionManager, InteractionSourceState, InteractionSource, InteractionSourceProperties, InteractionSourceKind, InteractionSourceLocation

Um ausführlichere Informationen zu Windows Mixed Reality Handeingaben (für HoloLens) und Bewegungscontrollern zu erhalten, können Sie die Windows-spezifischen APIs für räumliche Eingaben unter dem UnityEngine.XR.WSA.Input-Namespace verwenden. Auf diese Weise können Sie auf zusätzliche Informationen zugreifen, z. B. Positionsgenauigkeit oder die Art der Quelle, sodass Sie Hände und Controller voneinander trennen können.

Abfragen des Zustands von Händen und Bewegungscontrollern

Sie können den Status dieses Frames für jede Interaktionsquelle (Hand- oder Bewegungscontroller) mithilfe der GetCurrentReading-Methode abfragen.

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

Jeder InteractionSourceState , den Sie zurückerhalten, stellt eine Interaktionsquelle zum aktuellen Zeitpunkt dar. InteractionSourceState macht Informationen verfügbar, z. B.:

  • Welche Arten von Drücken auftreten (Auswählen/Menü/Greifen/Touchpad/Thumbstick)

    if (interactionSourceState.selectPressed) {
         // ...
    }
    
  • Andere spezifische Daten für Bewegungscontroller, z. B. die XY-Koordinaten des Touchpads und/oder des Fingerabdrucksticks und der touchierten Zustand

    if (interactionSourceState.touchpadTouched && interactionSourceState.touchpadPosition.x > 0.5) {
         // ...
    }
    
  • InteractionSourceKind, um zu ermitteln, ob es sich bei der Quelle um einen Hand- oder Bewegungscontroller handelt

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

Abfragen von vorwärts vorhergesagten Renderingposen

  • Beim Abfragen von Interaktionsquellendaten von Händen und Controllern sind die Posen, die Sie erhalten, vorwärts vorhergesagte Posen für den Zeitpunkt, zu dem die Photonen dieses Frames die Augen des Benutzers erreichen. Vorwärts vorhergesagte Posen werden am besten zum Rendern des Controllers oder eines gehaltenen Objekts für jeden Frame verwendet. Wenn Sie eine bestimmte Presse oder Veröffentlichung mit dem Controller als Ziel verwenden, ist dies am genauesten, wenn Sie die unten beschriebenen historischen Ereignis-APIs verwenden.

    var sourcePose = interactionSourceState.sourcePose;
    Vector3 sourceGripPosition;
    Quaternion sourceGripRotation;
    if ((sourcePose.TryGetPosition(out sourceGripPosition, InteractionSourceNode.Grip)) &&
         (sourcePose.TryGetRotation(out sourceGripRotation, InteractionSourceNode.Grip))) {
         // ...
    }
    
  • Sie können auch die vorwärts vorhergesagte Kopfposition für diesen aktuellen Frame abrufen. Wie bei der Quellposition ist dies für das Rendern eines Cursors nützlich, obwohl die Ausrichtung auf eine bestimmte Presse oder Veröffentlichung am genauesten ist, wenn Sie die unten beschriebenen historischen Ereignis-APIs verwenden.

    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;
         // ...
    }
    

Behandeln von Interaktionsquellenereignissen

Um Eingabeereignisse mit ihren genauen Verlaufsdaten zu behandeln, können Sie Interaktionsquellenereignisse behandeln, anstatt abfragen zu müssen.

So behandeln Sie Interaktionsquellenereignisse:

  • Registrieren Sie sich für ein InteractionManager-Eingabeereignis . Für jeden Typ von Interaktionsereignissen, an dem Sie interessiert sind, müssen Sie es abonnieren.

    InteractionManager.InteractionSourcePressed += InteractionManager_InteractionSourcePressed;
    
  • Behandeln Sie das Ereignis. Nachdem Sie ein Interaktionsereignis abonniert haben, erhalten Sie ggf. den Rückruf. Im SourcePressed-Beispiel erfolgt dies, nachdem die Quelle erkannt wurde und bevor sie freigegeben wird oder verloren geht.

    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
    }
    

So beenden Sie die Behandlung eines Ereignisses

Sie müssen die Behandlung eines Ereignisses beenden, wenn Sie nicht mehr an dem Ereignis interessiert sind oder das Objekt, das das Ereignis abonniert hat, zerstören. Um die Behandlung des Ereignisses zu beenden, kündigen Sie das Ereignis ab.

InteractionManager.InteractionSourcePressed -= InteractionManager_InteractionSourcePressed;

Liste der Interaktionsquellenereignisse

Die verfügbaren Interaktionsquellenereignisse sind:

  • InteractionSourceDetected (Quelle wird aktiv)
  • InteractionSourceLost (wird inaktiv)
  • InteractionSourcePressed (tippen, schaltfläche drücken oder "Auswählen" ausgesprochen)
  • InteractionSourceReleased (Ende eines Tippens, Schaltfläche losgelassen oder Ende von "Select" ausgesprochen)
  • InteractionSourceUpdated (verschiebt oder ändert auf andere Weise einen Zustand)

Ereignisse für historische Targeting-Posen, die einer Presse oder Veröffentlichung am besten entsprechen

Die zuvor beschriebenen Abruf-APIs geben Ihrer App vorausgesagte Posen. Während diese vorhergesagten Posen am besten zum Rendern des Controllers oder eines virtuellen Handheldobjekts geeignet sind, sind zukünftige Posen für die Ausrichtung aus zwei wichtigen Gründen nicht optimal:

  • Wenn der Benutzer eine Taste an einem Controller drückt, kann es etwa 20 ms drahtlose Latenz über Bluetooth geben, bevor das System die Taste erhält.
  • Wenn Sie dann eine vorwärts vorhergesagte Pose verwenden, werden weitere 10-20 ms Vorwärtsvorhersage angewendet, um den Zeitpunkt festzulegen, zu dem die Photonen des aktuellen Frames die Augen des Benutzers erreichen.

Dies bedeutet, dass Sie beim Abfragen eine Quellposition oder Kopfhaltung erhalten, die 30-40 ms vorwärts von der Stelle entfernt ist, an der der Kopf und die Hände des Benutzers tatsächlich zurück waren, als die Presse oder die Freigabe erfolgte. Bei der HoloLens-Handeingabe gibt es zwar keine Drahtlose Übertragungsverzögerung, aber es gibt eine ähnliche Verarbeitungsverzögerung, um die Presse zu erkennen.

Um eine genaue Ausrichtung basierend auf der ursprünglichen Absicht des Benutzers für eine Hand- oder Controller-Presse zu verwenden, sollten Sie die historische Quellpose oder Kopfhaltung aus diesem InteractionSourcePressed - oder InteractionSourceReleased-Eingabeereignis verwenden.

Sie können eine Presse oder eine Veröffentlichung mit historischen Posendaten vom Kopf des Benutzers oder dessen Controller als Ziel verwenden:

  • Die Kopfhaltung zu dem Zeitpunkt, zu dem eine Geste oder eine Controllertaste aufgetreten ist, die für die Ausrichtung verwendet werden kann, um zu bestimmen, was der Benutzer betrachtet hat:

    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;
             // ...
         }
    }
    
  • Die Quellposition zu dem Zeitpunkt, zu dem ein Motion Controller-Drücken aufgetreten ist, die für das Targeting verwendet werden kann, um zu bestimmen, worauf der Benutzer mit dem Controller zeigt. Dies ist der Zustand des Controllers, bei dem die Presse aufgetreten ist. Wenn Sie den Controller selbst rendern, können Sie die Zeigerposition anstelle der Griffposition anfordern, um den Zielstrahl von dem zu schießen, was der Benutzer als die natürliche Spitze des gerenderten Controllers betrachtet:

    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;
                 // ...
             }
         }
    }
    

Beispiel für Ereignishandler

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.
}

Motion Controller im MRTK

Sie können über den Eingabe-Manager auf gesten- und bewegungscontroller zugreifen.

Immer am Ball mit Tutorials

Schritt-für-Schritt-Tutorials mit ausführlicheren Anpassungsbeispielen finden Sie in der Mixed Reality Academy:

MR-Eingang 213 – Bewegungscontroller
MR-Eingang 213 – Bewegungscontroller

Nächster Entwicklungsprüfpunkt

Wenn Sie die von uns beschriebene Unity-Entwicklungsreise befolgen, befinden Sie sich mitten in der Erkundung der MRTK-Kernbausteine. Von hier aus können Sie mit dem nächsten Baustein fortfahren:

Oder fahren Sie mit den Funktionen und APIs der Mixed Reality-Plattform fort:

Sie können jederzeit zu den Prüfpunkten für die Unity-Entwicklung zurückkehren.

Siehe auch