Zeiger — MRTK2

Pointer

In diesem Artikel wird erläutert, wie Zeigereingaben in der Praxis konfiguriert und beantwortet werden. Weitere Informationen zum Steuern mehrerer Zeiger auf hoher Ebene finden Sie unter Zeigerarchitektur.

Zeiger werden automatisch zur Laufzeit instanziert, wenn ein neuer Controller erkannt wird. Mehrere Zeiger können an einen Controller angefügt werden. Mit dem Standardzeigerprofil erhalten Windows Mixed Reality Controller beispielsweise sowohl eine Linie als auch einen parabolischen Zeiger für normale Auswahl und Teleportierung.

Zeigerkonfiguration

Zeiger werden als Teil des Eingabesystems in MRTK über ein MixedRealityPointerProfile. Dieser Profiltyp wird einem MixedRealityInputSystemProfile im MRTK-Konfigurationsinspektor zugewiesen. Das Zeigerprofil bestimmt den Cursor, arten von Zeigern, die zur Laufzeit verfügbar sind, und wie diese Zeiger miteinander kommunizieren, um zu entscheiden, welche aktiv ist.

  • Pointing Extent – Definiert den maximalen Abstand, für den ein Zeiger mit einem GameObject interagieren kann.

  • Pointing Raycast Layer Masks - Dies ist ein priorisiertes Array von LayerMasks, um zu bestimmen, mit welchen möglichen GameObjects ein beliebiger Zeiger interagieren kann und mit der Reihenfolge der Interaktion zu versuchen. Dies kann hilfreich sein, um sicherzustellen, dass Zeiger zuerst mit UI-Elementen interagieren, bevor andere Szenenobjekte. Pointer Profile Example

Konfiguration von Zeigeroptionen

Die Standardmäßige MRTK-Zeigerprofilkonfiguration enthält die folgenden Zeigerklassen und zugeordnete Voreinstellungen. Die Liste der für das System zur Laufzeit verfügbaren Zeigerpunkte wird unter Zeigeroptionen im Zeigerprofil definiert. Entwickler können diese Liste verwenden, um vorhandene Zeiger neu zu konfigurieren, neue Zeiger hinzuzufügen oder eine zu löschen.

Pointer Options Profile Example

Jeder Zeigereintrag wird durch die folgende Datenmenge definiert:

  • Controllertyp – Der Satz von Controllern, für die ein Zeiger gültig ist.

    • Beispielsweise ist der PokePointer für "PokePointer " -Objekte mit einem Finger verantwortlich und ist standardmäßig als nur die Unterstützung des artikulierten Handcontrollertyps gekennzeichnet. Zeiger werden nur instanziiert, wenn ein Controller verfügbar wird und insbesondere der Controllertyp definiert, mit welchen Controllern dieser Zeiger-Prefab erstellt werden kann.
  • Händigkeit – ermöglicht es einem Zeiger, nur für eine bestimmte Hand instanziiert zu werden (links/rechts)

Hinweis

Wenn Sie die Eigenschaft "Händigkeit " eines Zeigers auf "None " festlegen, wird sie effektiv vom System als Alternative zum Entfernen dieses Zeigers aus der Liste deaktiviert.

  • Pointer Prefab – Dieses Prefab-Objekt wird instanziiert, wenn ein Controller, der dem angegebenen Controllertyp entspricht, und die Händigkeit beginnt, nachverfolgt wird.

Es ist möglich, mehrere Zeiger mit einem Controller verknüpft zu haben. Beispielsweise ist der artikulierte Handcontroller in DefaultHoloLens2InputSystemProfile (Assets/MRTK/SDK/Profiles/HoloLens2/) dem PokePointer, GrabPointer und dem DefaultControllerPointer (z. B. Handstrahlen) zugeordnet.

Hinweis

MRTK bietet eine Reihe von Zeiger-Prefabs in Assets/MRTK/SDK/Features/UX/Prefabs/Pointers. Ein neuer benutzerdefinierter Prefab kann erstellt werden, solange er eines der Zeigerskripts in Assets/MRTK/SDK/Features/UX/Scripts/Pointers oder ein anderes Skript implementiert IMixedRealityPointer.

Cursorkonfiguration

Der Blickcursor kann direkt über die GazeCursorPrefab Eigenschaft im MixedRealityInputSystemProfile Editor konfiguriert werden. Zum Konfigurieren des Cursors, der für andere Zeiger verwendet wird, müssen Sie prefab ändern, der CursorPrefab im Feld der entsprechenden BaseControllerPointer. Um den Cursor programmgesteuert zu ändern, ändern Sie die BaseCursor Eigenschaft für das entsprechende IMixedRealityPointer Verhalten.

Cursor Prefab Property

Sehen Sie sich unsere Cursorvorschauen in Assets/MRTK/SDK/Features/UX/Prefabs/Cursors an, z. B. Implementierungen des Cursorverhaltens. Insbesondere gibt der DefaultGazeCursor eine robuste Implementierung des Änderns der Grafik des Cursors basierend auf kontextbezogenem Zustand.

Standardzeigerklassen

Die folgenden Klassen sind die out-of-box MRTK-Zeiger verfügbar und in dem oben beschriebenen MRTK-Zeigerprofil definiert. Jeder Zeiger prefab, der unter Assets/MRTK/SDK/Features/UX/Prefabs/Pointers bereitgestellt wird, enthält eine der angefügten Zeigerkomponenten.

MRTK Default Pointers

Weit zeigende Zeiger

LinePointer

LinePointer, eine Basiszeigerklasse, zeichnet eine Linie aus der Quelle der Eingabe (d. h. dem Controller) in der Zeigerrichtung und unterstützt eine einzelne Ray-Umwandlung in diese Richtung. Im Allgemeinen werden untergeordnete Klassen wie die ShellHandRayPointer und die Teleportzeiger instanziiert und verwendet (die auch Linien zeichnen, um anzugeben, wo Teleportation enden wird) anstelle dieser Klasse, die hauptsächlich allgemeine Funktionen bereitstellt.

Bei Bewegungscontrollern wie in Oculus, Vive und Windows Mixed Reality entspricht die Drehung der Drehung der Drehung des Controllers. Bei anderen Controllern wie HoloLens 2 artikulierten Händen entspricht die Drehung der vom System bereitgestellten Zeigepose der Hand.

MRTK Pointer Line
CurvePointer

CurvePointer erweitert die LinePointer-Klasse , indem sie mehrstufige Ray-Umwandlungen entlang einer Kurve ermöglicht. Diese Basiszeigerklasse ist nützlich für gekrümmte Instanzen wie Teleportationszeiger, bei denen die Linie konsistent in eine Parabola gekrümmt wird.

ShellHandRayPointer

Die Implementierung von ShellHandRayPointer, der sich aus LinePointererweitert, wird als Standard für das MRTK-Zeigerprofil verwendet. Der DefaultControllerPointer-Prefab implementiert die ShellHandRayPointer Klasse.

GGVPointer

Auch bekannt als Blick/Geste/Voice (GGV)-Zeiger, macht der GGVPointer HoloLens 1-Stil-Aussehen und tippen Sie interaktionen, hauptsächlich über Blick und Luft tippen oder Per Blick oder Blick und Sprachauswahlinteraktion. Die Position und Richtung des GGV-Zeigers wird durch die Position und Drehung des Kopfes gesteuert.

TouchPointer

Der TouchPointer ist für die Arbeit mit Unity Touch-Eingabe (d. h. Touchscreen) verantwortlich. Dies sind "weit interaktionen", da der Akt des Berührens des Bildschirms einen Ray von der Kamera in eine potenziell weit entfernte Position in der Szene umwandeln wird.

MousePointer

Der MousePointer macht einen Bildschirm zur Welt-Raycast für viele Interaktionen, aber für Maus anstelle von Toucheingaben.

Mouse pointer

Hinweis

Die Mausunterstützung ist in MRTK nicht standardmäßig verfügbar, kann jedoch aktiviert werden, indem sie dem MRTK-Eingabeprofil einen neuen Eingabe-DatenanbieterMouseDeviceManager hinzufügen und dem MixedRealityMouseInputProfile Datenanbieter zuweisen.

Nahzeiger

PokePointer

Der PokePointer wird verwendet, um mit Spielobjekten zu interagieren, die "in der Nähe der Interaktion berührend" unterstützen. die GameObjects sind, die über ein angefügtes NearInteractionTouchable Skript verfügen. Bei UnityUI sucht dieser Zeiger nach NearInteractionTouchableUnityUIs. Der PokePointer verwendet einen SphereCast, um das nächstgelegene touchierbare Element zu bestimmen und wird verwendet, um Dinge wie die druckbaren Tasten zu aktivieren.

Wenn Sie das GameObject mit der NearInteractionTouchable Komponente konfigurieren, müssen Sie den lokalenForward-Parameter so konfigurieren, dass er auf die Vorderseite der Schaltfläche oder eines anderen Objekts verweist, das touchierbar gemacht werden soll. Stellen Sie außerdem sicher, dass die Grenzen des touchierbaren Objekts mit den Grenzen des touchierbaren Objekts übereinstimmen.

Nützliche Poke Pointer-Eigenschaften:

  • TouchableDistance: Maximaler Abstand, in dem eine touchierbare Oberfläche interagiert werden kann
  • Visuelle Elemente: Spielobjekt, das zum Rendern von Fingerspitzen verwendet wird (der Ring auf dem Finger standardmäßig).
  • Linie: Optionale Linie, die von der Fingerspitze bis zur aktiven Eingabeoberfläche zeichnen soll.
  • Poke Layer Masks – Ein priorisiertes Array von LayerMasks, um zu bestimmen, mit welchem möglichen GameObjects der Zeiger interagieren kann, und mit der Reihenfolge der Interaktion zu versuchen. Beachten Sie, dass ein GameObject auch über eine NearInteractionTouchable Komponente verfügen muss, um mit einem Pokezeiger zu interagieren.
Poke Pointer
SpherePointer

Der SpherePointer verwendet UnityEngine.Physics.OverlapSphere , um das nächstgelegene NearInteractionGrabbable Objekt für die Interaktion zu identifizieren, was für "grabbable" Eingaben wie die ManipulationHandler. Ähnlich wie das PokePointer/NearInteractionTouchable funktionale Paar muss das Spielobjekt eine Komponente enthalten, die das NearInteractionGrabbable Skript ist, um mit dem Kugelzeiger interagierbar zu sein.

Grab Pointer

Nützliche Kugelzeigereigenschaften:

  • Kugel-Umwandlungsradius: Der Radius für die Kugel, die zum Abfragen von greifbaren Objekten verwendet wird.
  • In der Nähe des Objektrands: Der Abstand über dem Kugel-Cast-Radius, um abzufragen, ob ein Objekt in der Nähe des Zeigers liegt. Total Near Object detection radius is Sphere Cast Radius + Near Object Margin
  • Near Object Sector Angle: Der Winkel um die Vorwärtsachse des Zeigers zum Abfragen nach nahe gelegenen Objekten. Macht die IsNearObject Abfragefunktion wie ein Kegel. Dies ist standardmäßig auf 66 Grad festgelegt, um dem Verhalten von Hololens 2 zu entsprechen.

Sphere pointer modified to only query for objects in the forward direction

  • Near Object Smoothing Factor: Glättungsfaktor für die Erkennung von Nahobjekten. Wenn ein Objekt im Nahobjektradius erkannt wird, wird der abgefragte Radius dann zu Near Object Radius * (1 + Near Object Smoothing Factor), um die Vertraulichkeit zu verringern und es einem Objekt schwieriger zu machen, den Erkennungsbereich zu verlassen.
  • Grab Layer Masks - Ein priorisiertes Array von LayerMasks, um zu bestimmen, mit welchen möglichen GameObjects der Zeiger interagieren kann, und mit der Reihenfolge der Interaktion zu versuchen. Beachten Sie, dass ein GameObject auch über eine NearInteractionGrabbable Interaktion mit einem SpherePointer verfügen muss.

    Hinweis

    Die Spatial Awareness-Ebene ist in der standardmäßigen GrabPointer-Prefab, die von MRTK bereitgestellt wird, deaktiviert. Dies geschieht, um die Leistungsauswirkungen einer Kugelüberschneidungsabfrage mit dem räumlichen Gitter zu verringern. Sie können dies aktivieren, indem Sie den GrabPointer-Prefab ändern.

  • Colliders Nicht in FOV ignorieren – Gibt an, ob Collider ignoriert werden sollen, die sich möglicherweise in der Nähe des Zeigers befinden, aber nicht tatsächlich im visuellen FOV. Dies kann versehentliche Greifer verhindern und die Handstrahlen aktivieren, wenn Sie möglicherweise in der Nähe eines greifbaren, aber nicht sehen können. Der Visuelle FOV wird aus Leistungsgründen über einen Kegel anstelle des typischen Frustums definiert. Dieser Kegel ist zentriert und ausgerichtet wie das Frustum der Kamera mit einem Radius, der der halber Anzeigehöhe (oder vertikaler FOV) entspricht.
Sphere Pointer

Teleportzeiger

  • TeleportPointer löst eine Teleportanforderung aus, wenn die Aktion ausgeführt wird (d. h. die Teleportschaltfläche wird gedrückt), um den Benutzer zu verschieben.
  • ParabolicTeleportPointer löst eine Teleportanforderung aus, wenn die Aktion ausgeführt wird (d. h. die Teleportschaltfläche wird gedrückt) mit einem parabolischen Linienstrahlcast, um den Benutzer zu verschieben.
Pointer Parabolic

Zeigerunterstützung für Mixed Reality-Plattformen

In der folgenden Tabelle sind die Zeigertypen aufgeführt, die in der Regel für die gängigen Plattformen in MRTK verwendet werden. HINWEIS: Es ist möglich, diesen Plattformen verschiedene Zeigertypen hinzuzufügen. Sie können z. B. einen Poke-Zeiger oder einen Kugelzeiger zu VR hinzufügen. Darüber hinaus könnten VR-Geräte mit einem Gamepad den GGV-Zeiger verwenden.

Zeiger OpenVR Windows Mixed Reality HoloLens 1 HoloLens 2
ShellHandRayPointer Gültig Gültig Gültig
TeleportPointer Gültig Gültig
GGVPointer Gültig
SpherePointer Gültig
PokePointer Gültig

Zeigerinteraktionen über Code

Zeigerereignisschnittstellen

MonoBehaviours, die eine oder mehrere der folgenden Schnittstellen implementieren und einem GameObject mit Collider einem GameObject zugewiesen werden, erhalten Zeigerinteraktionen, wie durch die zugeordnete Schnittstelle definiert.

Ereignis Beschreibung Handler
Bevor der Fokus geändert / Fokus geändert wurde Ausgelöst auf das Spielobjekt, das den Fokus verliert und dies jedes Mal, wenn ein Zeiger den Fokus ändert. IMixedRealityFocusChangedHandler
Fokuseingabe / Beenden Ausgelöst auf das Spielobjekt, das den Fokus erhält, wenn der erste Zeiger ihn eingibt und auf der einen verliert, wenn der letzte Zeiger ihn verlässt. IMixedRealityFocusHandler
Zeiger nach unten / Nach oben / geklickt / geklickt Wird zum Melden von Zeiger drücken, ziehen und freigeben. IMixedRealityPointerHandler
Touchstart / Aktualisiert / abgeschlossen Ausgelöst durch Toucheingabezeiger, die PokePointer Toucheingabeaktivität melden möchten. IMixedRealityTouchHandler

Hinweis

IMixedRealityFocusChangedHandler und IMixedRealityFocusHandler sollte in den Objekten behandelt werden, auf denen sie ausgelöst werden. Es ist möglich, Fokusereignisse global zu empfangen, aber im Gegensatz zu anderen Eingabeereignissen blockiert der globale Ereignishandler nicht den Empfang von Ereignissen basierend auf dem Fokus (das Ereignis wird sowohl vom globalen Handler als auch von einem entsprechenden Objekt im Fokus empfangen).

Zeigereingabeereignisse in Aktion

Zeigereingabeereignisse werden von dem MRTK-Eingabesystem auf ähnliche Weise wie normale Eingabeereignisse erkannt und behandelt. Der Unterschied darin, dass Zeigereingabeereignisse nur vom GameObject im Fokus vom Zeiger behandelt werden, der das Eingabeereignis ausgelöst hat, sowie alle globalen Eingabehandler. Regelmäßige Eingabeereignisse werden von GameObjects im Fokus für alle aktiven Zeiger behandelt.

  1. Das MRTK-Eingabesystem erkennt ein Eingabeereignis.
  2. Das MRTK-Eingabesystem löst die relevante Schnittstellenfunktion für das Eingabeereignis auf alle registrierten globalen Eingabehandler aus.
  3. Das Eingabesystem bestimmt, welche GameObject im Fokus für den Zeiger steht, der das Ereignis ausgelöst hat.
    1. Das Eingabesystem verwendet das Unity-Ereignissystem , um die relevante Schnittstellenfunktion für alle übereinstimmenden Komponenten auf dem fokussierten GameObject zu auslösen.
    2. Wenn an irgendeinem Punkt ein Eingabeereignis als verwendet markiert wurde, wird der Prozess beendet und keine weiteren GameObjects erhalten Rückrufe.
      • Beispiel: Komponenten, die die Schnittstelle IMixedRealityFocusHandler implementieren, werden nach einem GameObject-Objekt gesucht oder verliert den Fokus.
      • Hinweis: Das Unity-Ereignissystem wird nach dem übergeordneten GameObject durchsucht, wenn keine Komponenten, die der gewünschten Schnittstelle entsprechen, auf dem aktuellen GameObject gefunden werden.
  4. Wenn keine globalen Eingabehandler registriert sind und kein GameObject mit einer übereinstimmenden Komponente/Schnittstelle gefunden wird, ruft das Eingabesystem jede Fallback-registrierten Eingabehandler auf.

Beispiel

Unten ist ein Beispielskript, das die Farbe des angefügten Renderers ändert, wenn ein Zeiger den Fokus nimmt oder verlässt oder wenn ein Zeiger das Objekt markiert.

public class ColorTap : MonoBehaviour, IMixedRealityFocusHandler, IMixedRealityPointerHandler
{
    private Color color_IdleState = Color.cyan;
    private Color color_OnHover = Color.white;
    private Color color_OnSelect = Color.blue;
    private Material material;

    private void Awake()
    {
        material = GetComponent<Renderer>().material;
    }

    void IMixedRealityFocusHandler.OnFocusEnter(FocusEventData eventData)
    {
        material.color = color_OnHover;
    }

    void IMixedRealityFocusHandler.OnFocusExit(FocusEventData eventData)
    {
        material.color = color_IdleState;
    }

    void IMixedRealityPointerHandler.OnPointerDown(
         MixedRealityPointerEventData eventData) { }

    void IMixedRealityPointerHandler.OnPointerDragged(
         MixedRealityPointerEventData eventData) { }

    void IMixedRealityPointerHandler.OnPointerClicked(MixedRealityPointerEventData eventData)
    {
        material.color = color_OnSelect;
    }
}

Abfragezeiger

Es ist möglich, alle Zeiger zu sammeln, die derzeit aktiv sind, indem Sie die verfügbaren Eingabequellen (d. h. Controller und Eingaben verfügbar) durchlaufen, um zu ermitteln, welche Zeiger an sie angefügt werden.

var pointers = new HashSet<IMixedRealityPointer>();

// Find all valid pointers
foreach (var inputSource in CoreServices.InputSystem.DetectedInputSources)
{
    foreach (var pointer in inputSource.Pointers)
    {
        if (pointer.IsInteractionEnabled && !pointers.Contains(pointer))
        {
            pointers.Add(pointer);
        }
    }
}

Primärer Zeiger

Entwickler können das FocusProviders PrimaryPointerChanged-Ereignis abonnieren, um benachrichtigt zu werden, wenn der primäre Zeiger im Fokus geändert wurde. Dies kann äußerst nützlich sein, um zu identifizieren, ob der Benutzer derzeit mit einer Szene über Blick oder Handstrahl oder eine andere Eingabequelle interagiert.

private void OnEnable()
{
    var focusProvider = CoreServices.InputSystem?.FocusProvider;
    focusProvider?.SubscribeToPrimaryPointerChanged(OnPrimaryPointerChanged, true);
}

private void OnPrimaryPointerChanged(IMixedRealityPointer oldPointer, IMixedRealityPointer newPointer)
{
    ...
}

private void OnDisable()
{
    var focusProvider = CoreServices.InputSystem?.FocusProvider;
    focusProvider?.UnsubscribeFromPrimaryPointerChanged(OnPrimaryPointerChanged);

    // This flushes out the current primary pointer
    OnPrimaryPointerChanged(null, null);
}

Die PrimaryPointerExample Szene (Assets/MRTK/Examples/Demos/Input/Scenes/PrimaryPointer) zeigt, wie Sie die PrimaryPointerChangedHandler Ereignisse verwenden, um auf einen neuen primären Zeiger zu reagieren.

Primary Pointer Example

Zeigerergebnis

Die Zeigereigenschaft Result enthält das aktuelle Ergebnis für die Szenenabfrage, die zum Ermitteln des Objekts mit Fokus verwendet wird. Für einen Raycast-Zeiger, wie dies standardmäßig für Bewegungscontroller, Blickeingaben und Handstrahlen erstellt wurde, enthält er die Position und normal des Raycast-Treffers.

private void IMixedRealityPointerHandler.OnPointerClicked(MixedRealityPointerEventData eventData)
{
    var result = eventData.Pointer.Result;
    var spawnPosition = result.Details.Point;
    var spawnRotation = Quaternion.LookRotation(result.Details.Normal);
    Instantiate(MyPrefab, spawnPosition, spawnRotation);
}

Die PointerResultExample Szene (Assets/MRTK/Examples/Demos/Input/Scenes/PointerResultExample.unity) zeigt, wie der Zeiger Result zum Spawenn eines Objekts an der Trefferposition verwendet wird.

Pointer Result

Deaktivieren von Zeigern

Um Zeiger zu aktivieren und zu deaktivieren (z. B. zum Deaktivieren des Handstrahls), legen Sie die PointerBehavior Option für einen bestimmten Zeigertyp über PointerUtils.

// Disable the hand rays
PointerUtils.SetHandRayPointerBehavior(PointerBehavior.AlwaysOff);

// Disable hand rays for the right hand only
PointerUtils.SetHandRayPointerBehavior(PointerBehavior.AlwaysOff, Handedness.Right);

// Disable the gaze pointer
PointerUtils.SetGazePointerBehavior(PointerBehavior.AlwaysOff);

// Set the behavior to match HoloLens 1
// Note, if on HoloLens 2, you must configure your pointer profile to make the GGV pointer show up for articulated hands.
public void SetHoloLens1()
{
    PointerUtils.SetPokePointerBehavior(PointerBehavior.AlwaysOff, Handedness.Any);
    PointerUtils.SetGrabPointerBehavior(PointerBehavior.AlwaysOff, Handedness.Any);
    PointerUtils.SetRayPointerBehavior(PointerBehavior.AlwaysOff, Handedness.Any);
    PointerUtils.SetGGVBehavior(PointerBehavior.Default);
}

Weitere Beispiele finden Sie unter PointerUtils und TurnPointersOnOff für weitere Beispiele.

Zeigerinteraktionen über den Editor

Für Zeigerereignisse, die von IMixedRealityPointerHandlerMRTK behandelt werden, bietet MRTK weitere Komfort in Form der PointerHandler Komponente, wodurch Zeigerereignisse direkt über Unity-Ereignisse behandelt werden können.

Pointer Handler

Zeigerausdehnung

Weit zeigende Zeiger haben Einstellungen, die einschränken, wie weit sie raycasten und mit anderen Objekten in der Szene interagieren. Standardmäßig ist dieser Wert auf 10 Meter festgelegt. Dieser Wert wurde ausgewählt, um mit dem Verhalten der HoloLens Shell konsistent zu bleiben.

Dies kann geändert werden, indem Sie die Felder der DefaultControllerPointer Komponente des Prefabs ShellHandRayPointer aktualisieren:

Zeigerausmaß – Dadurch wird der maximale Abstand gesteuert, mit dem Zeiger interagieren.

Standardzeigerausmaß – Dadurch wird die Länge des Zeigerstrahls/der Linie gesteuert, die gerendert wird, wenn der Zeiger nicht mit etwas interagieren wird.

Siehe auch