Zeiger

Zeiger

In diesem Artikel wird erläutert, wie Zeigereingaben in der Praxis im Vergleich zur Zeigerarchitektur konfiguriert und darauf reagiert werden.

Zeiger werden zur Laufzeit automatisch instanziert, wenn ein neuer Controller erkannt wird. An einen Controller können mehrere Zeiger angefügt werden. Beispielsweise erhalten Windows Mixed Reality Controller mit dem Standardzeigerprofil sowohl eine Linie als auch einen parabolischen Zeiger für die normale Auswahl bzw. Teleportierung.

Zeigerkonfiguration

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

  • Zeigender Umfang: Definiert den maximalen Abstand, für den ein Zeiger mit einem GameObject interagieren kann.

  • Verweisen auf Raycast-Ebenenmasken: Dies ist ein priorisiertes Array von LayerMasks, um zu bestimmen, mit welchen möglichen GameObjects ein bestimmter Zeiger interagieren kann, und die Reihenfolge der Interaktion, die versucht werden soll. Dies kann hilfreich sein, um sicherzustellen, dass Zeiger zuerst mit Benutzeroberflächenelementen vor anderen Szenenobjekten interagieren. Beispiel für Zeigerprofil

Konfiguration von Zeigeroptionen

Die STANDARDMÄßIGE MRTK-Zeigerprofilkonfiguration umfasst die folgenden Zeigerklassen und zugeordneten Prefabs standardmäßig. Die Liste der Zeiger, die zur Laufzeit für das System verfügbar sind, wird unter Zeigeroptionen im Zeigerprofil definiert. Entwickler können diese Liste verwenden, um vorhandene Zeiger neu zu konfigurieren, neue Zeiger hinzuzufügen oder einen zu löschen.

Beispiel für Zeigeroptionenprofil

Jeder Zeigereintrag wird durch den folgenden Satz von Daten definiert:

  • Controllertyp: Die Gruppe von Controllern, für die ein Zeiger gültig ist.

    • So ist beispielsweise Der -Pointer für das "Zeichnen" von Objekten mit einem Finger verantwortlich und standardmäßig als nur für die Unterstützung des artikulierten Handcontrollertyps markiert. Zeiger werden nur instanziiert, wenn ein Controller verfügbar wird und insbesondere der Controllertyp definiert, mit welchen Controllern dieses Zeigerpräfab erstellt werden kann.
  • Handkraft: Ermöglicht, dass ein Zeiger auf nur für eine bestimmte Hand instanziiert wird (links/rechts).

Hinweis

Wenn Sie die Eigenschaft "Handkraft" eines Zeigereintrags auf "None" festlegen, wird sie im System als Alternative zum Entfernen dieses Zeigers aus der Liste deaktiviert.

  • Zeiger-Prefab: Dieses Prefab-Medienobjekt wird instanziiert, wenn ein Controller, der dem angegebenen Controllertyp entspricht, und die Übergabe nachverfolgt wird.

Es ist möglich, einem Controller mehrere Zeiger zuzuordnen. Beispiel: In DefaultHoloLens2InputSystemProfile (Assets/MRTK/SDK/Profiles/HoloLens2/) ist der artikulierte Handcontroller mit dem DefaultHoloLens2InputSystemProfiledem GrabPointerund dem DefaultControllerPointer (Handlicht) verknüpft.

Hinweis

MRTK stellt einen Satz von Zeigerpräfabs in Assets/MRTK/SDK/Features/UX/Prefabs/Pointers bereit. Ein neues benutzerdefiniertes Prefab kann erstellt werden, solange es eines der Zeigerskripts in Assets/MRTK/SDK/Features/UX/Scripts/Pointers oder ein anderes Skript enthält, das implementiert.

Standardzeigerklassen

Die folgenden Klassen sind die standardmäßig verfügbaren MRTK-Zeiger, die im oben beschriebenen MRTK-Standardzeigerprofil definiert sind. Jedes unter Assets/MRTK/SDK/Features/UX/Prefabs/Pointers bereitgestellte Zeiger-Prefab enthält eine der angefügten Zeigerkomponenten.

MRTK-Standardzeiger

Fernzeiger

LinePointer

LinePointer, eine Basiszeigerklasse, zeichnet eine Linie aus der Quelle der Eingabe (d. h. dem Controller) in Zeigerrichtung und unterstützt einen einzelnen Strahl in dieser Richtung. Im Allgemeinen werden untergeordnete Klassen wie und ShellHandRayPointer die Teleportzeiger instanziiert und verwendet (die auch Linien zeichnen, um anzugeben, wo die Teleportierung enden soll) anstelle dieser Klasse, die in erster Linie allgemeine Funktionen bereitstellt.

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

MRTK-Zeigerlinie
CurvePointer

CurvePointer erweitert die LinePointer-Klasse, indem mehrstufige Raycasts entlang einer Kurve ermöglicht werden. Diese Basiszeigerklasse eignet sich für gekrümmte Instanzen, z. B. Teleportierungszeiger, bei denen die Linie konsistent in eine Parabel zerrend wird.

ShellHandRayPointer

Die Implementierung von ShellHandRayPointer, die von erweitert wird, wird als Standard für das MRTK-Zeigerprofilverwendet. Das DefaultControllerPointer-Prefab implementiert die -Klasse.

GGVPointer

Der GGVPointer wird auch als GGV-Zeiger (Gaze/Gesture/Voice) bezeichnet und unterstützt HoloLens 1-seitigen Look-and-Tap-Interaktionen, hauptsächlich über Anvisieren und Tippen in die Luft oder Interaktion mit Anvisieren und Sprachauswahl. Position und Richtung des GGV-Zeigers werden durch die Position und Drehung des Kopfs gesteuert.

TouchPointer

Der TouchPointer ist für die Arbeit mit Unity Touch Input (d.h. Touchscreen) verantwortlich. Dies sind "ferne Interaktionen", da durch das Berühren des Bildschirms ein Strahl von der Kamera in eine potenziell weit entfernte Position in der Szene geworfen wird.

MousePointer

Der MousePointer treibt einen Bildschirm für Ferninteraktionen, aber für Maus anstelle von Toucheingabe zum World Raycast.

Mauszeiger

Hinweis

Die Mausunterstützung ist im MRTK standardmäßig nicht verfügbar, kann jedoch aktiviert werden, indem dem MRTK-Eingabeprofil eine neue Eingabe-Datenanbieter vom Typ hinzugefügt und dem Datenanbieter zugewiesen MixedRealityMouseInputProfile wird.

Zeiger in der Nähe

PokePointer

Der PointePointer wird verwendet, um mit Spielobjekten zu interagieren, die "nah anstreifbare Interaktionen" unterstützen. Dies sind GameObjects, die über ein angefügtes NearInteractionTouchable Skript verfügen. Im Fall von UnityUI sucht dieser Zeiger nach NearInteractionTouchableUnityUIs. Der BedePointer verwendet einen SphereCast, um das nächstgelegene touchierbare Element zu bestimmen, und wird verwendet, um Dinge wie die drückbaren Schaltflächen zu schalten.

Stellen Sie beim Konfigurieren des GameObject-Objekts mit der NearInteractionTouchable -Komponente sicher, dass Sie den NearInteractionTouchable so konfigurieren, dass er auf die Vorderseite der Schaltfläche oder auf ein anderes Objekt verweist, das anstreifbar gemacht werden soll. Stellen Sie außerdem sicher, dass die Begrenzungen des touchierbaren Objekts mit den Begrenzungen des touchierbaren Objekts übereinstimmen.

Nützliche Eigenschaften des Zeigerzeigers:

  • TouchableDistance:Maximaler Abstand, in dem eine touchierbare Oberfläche interagiert werden kann
  • Visuals:Spielobjekt, das zum Rendern von Fingertippvisuals verwendet wird (standardmäßig der Ring am Finger).
  • Linie:Optionale Linie, die von der Fingerspitze auf die aktive Eingabeoberfläche gezeichnet werden soll.
  • Layer Masks :Ein priorisiertes Array von LayerMasks, um zu bestimmen, mit welchen möglichen GameObjects der Zeiger interagieren kann, und die Reihenfolge der Interaktion, die versucht werden soll. Beachten Sie, dass ein GameObject auch über eine -Komponente verfügen NearInteractionTouchable muss, um mit einem Mauszeiger zu interagieren.
Zeiger
SpherePointer

SpherePointer verwendet UnityEngine.Physics.OverlapSphere, um das nächstgelegene Objekt für die Interaktion zu identifizieren. Dies ist nützlich für "greifbare" Eingaben wie . Ähnlich wie beim PokePointer/NearInteractionTouchable Funktionspaar muss das Spielobjekt eine Komponente enthalten, die das Skript ist, um mit dem Kugelzeiger interagieren zu NearInteractionGrabbable können.

Greifen des Zeigers

Nützliche Sphere-Zeigereigenschaften:

  • Kugel-Umwandlungsradius:Der Radius für die Kugel, die zum Abfragen von gierbaren Objekten verwendet wird.
  • Near Object Margin (Nahes Objektrand):Der Abstand über dem Radius der Kugelcast, der abgefragt werden soll, um zu ermitteln, ob sich ein Objekt in der Nähe des Zeigers befindet. Der Erkennungsradius des gesamten near-Objekts ist "Sphere Cast Radius + Near Object Margin".
  • Near Object Sector Angle:Der Winkel um die Vorwärtsachse des Zeigers zum Abfragen von Objekten in der Nähe. Macht die IsNearObject Abfragefunktion wie einen Kegel. Dies ist standardmäßig auf 66 Grad festgelegt, um dem Hololens 2-Verhalten zu entsprechen.

Kugelzeiger geändert, um nur Objekte in Vorwärtsrichtung abzufragen

  • Near Object Smoothing Factor: Glättungsfaktor für die Near Object-Erkennung. Wenn ein Objekt im Near Object Radius erkannt wird, wird der abgefragte Radius zu Near Object Radius * (1 + Near Object Smoothing Factor), um die Empfindlichkeit zu reduzieren und es für ein 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 die Reihenfolge der Interaktion, die versucht werden soll. Beachten Sie, dass ein GameObject auch über eine NearInteractionGrabbable verfügen muss, um mit einem SpherePointer zu interagieren.

    Hinweis

    Die Spatial Awareness-Ebene ist im standardmäßigen GrabPointer-Prefab deaktiviert, das vom MRTK bereitgestellt wird. Dies wird durchgeführt, um die Auswirkungen einer Kugelüberlappungsabfrage mit dem räumlichen Gitternetz auf die Leistung zu reduzieren. Sie können dies aktivieren, indem Sie das GrabPointer-Prefab ändern.

  • Collider ignorieren Nicht in FOV: Gibt an, ob Collider ignoriert werden sollen, die sich möglicherweise in der Nähe des Zeigers, aber nicht tatsächlich im visuellen FOV-Bereich befindet. Dies kann versehentliches Greifen verhindern und das Einschalten von Handlicht ermöglichen, wenn Sie sich möglicherweise in der Nähe eines Grabbings, aber nicht sehen können. Visual FOV wird aus Leistungsgründen über einen Kegel anstelle des typischen Frustums definiert. Dieser Kegel ist zentriert und gleich ausgerichtet wie das Frustum der Kamera mit einem Radius, der der halben Anzeigehöhe (oder vertikalen FOV) entspricht.
Kugelzeiger

Teleportzeiger

  • TeleportPointer wird eine Teleportanforderung ausgelöst, wenn eine Aktion ausgeführt wird (d. h., die Teleportschaltfläche wird gedrückt), um den Benutzer zu verschieben.
  • ParabolicTeleportPointer wird eine Teleportanforderung ausgelöst, wenn eine Aktion ausgeführt wird (d. h., die Teleportschaltfläche wird gedrückt) mit einem Parabollinien-Raycast, um den Benutzer zu verschieben.
Zeigerparabolisch

Zeigerunterstützung für Mixed Reality-Plattformen

In der folgenden Tabelle werden die Zeigertypen aufgeführt, die in der Regel für die allgemeinen Plattformen im MRTK verwendet werden. HINWEIS: Es ist möglich, diesen Plattformen verschiedene Zeigertypen hinzuzufügen. Sie können beispielsweise einen Poke-Zeiger oder einen Sphere-Zeiger zu VR hinzufügen. Darüber hinaus können 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 einem zugewiesen sind, empfangen Ereignisse für Zeigerinteraktionen, wie von der zugeordneten Collider Schnittstelle definiert.

Ereignis Beschreibung Handler
Vor Fokusänderung/Fokusänderung Wird ausgelöst, wenn sowohl das Spielobjekt den Fokus verliert als auch das, das es jedes Mal gewinnt, wenn ein Zeiger den Fokus ändert. IMixedRealityFocusChangedHandler
Focus Enter/Exit Wird auf dem Spielobjekt ausgelöst, das den Fokus verliert, wenn der erste Zeiger in das Objekt eintritt, und auf den, der den Fokus verliert, wenn der letzte Zeiger ihn verlässt. IMixedRealityFocusHandler
Zeiger nach unten/Gezogen/Nach oben/Klick Wird zum Drücken, Ziehen und Lassen des Berichtszeigers ausgelöst. IMixedRealityPointerHandler
Touch gestartet/aktualisiert/abgeschlossen Wird durch berührungsbasierte Zeiger wie ausgelöst, PokePointer um Touchaktivitäten zu melden. IMixedRealityTouchHandler

Hinweis

IMixedRealityFocusChangedHandler und IMixedRealityFocusHandler sollten in den Objekten behandelt werden, für die sie ausgelöst werden. Es ist möglich, Fokusereignisse global zu empfangen, aber im Gegensatz zu anderen Eingabeereignissen blockiert der globale Ereignishandler den Empfang von Ereignissen nicht 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 vom MRTK-Eingabesystem auf ähnliche Weise wie reguläre Eingabeereignisse erkannt und behandelt. Der Unterschied besteht in der Behandlung von Zeigereingabeereignissen nur durch das GameObject im Fokus durch den Zeiger, der das Eingabeereignis ausgelöst hat, sowie durch alle globalen Eingabehandler. Reguläre Eingabeereignisse werden von GameObjects im Fokus für alle aktiven Zeiger behandelt.

  1. Das MRTK-Eingabesystem erkennt, dass ein Eingabeereignis aufgetreten ist.
  2. Das MRTK-Eingabesystem gibt die relevante Schnittstellenfunktion für das Eingabeereignis für alle registrierten globalen Eingabehandler aus.
  3. Das Eingabesystem bestimmt, welches GameObject sich im Fokus für den Zeiger befindet, 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 verwenden.
    2. Wenn zu einem beliebigen Zeitpunkt ein Eingabeereignis als verwendet markiert wurde,wird der Prozess beendet, und keine weiteren GameObjects erhalten Rückrufe.
      • Beispiel: Komponenten, die die Schnittstelle implementieren, werden nach einem GameObject durchsucht, das den Fokus erhält IMixedRealityFocusHandler oder verliert.
      • Hinweis: Das Unity-Ereignissystem blasen hoch, um das übergeordnete GameObject zu durchsuchen, wenn im aktuellen GameObject keine Komponenten gefunden werden, die mit der gewünschten Schnittstelle übereinstimmen.
  4. Wenn keine globalen Eingabehandler registriert sind und kein GameObject mit einer übereinstimmenden Komponente/Schnittstelle gefunden wird, dann wird das Eingabesystem jeden fallback registrierten Eingabehandler aufrufen.

Beispiel

Im Folgenden finden Sie ein Beispielskript, das die Farbe des angefügten Renderers ändert, wenn ein Zeiger den Fokus übernimmt oder verlässt oder wenn ein Zeiger das Objekt auswählt.

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

Abfragezeker

Es ist möglich, alle zeiger, die derzeit aktiv sind, zu sammeln, indem Sie eine Schleife durch die verfügbaren Eingabequellen (d. h. verfügbare Controller und Eingaben) laufen, um zu erfahren, welche Zeiger an sie angefügt sind.

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 PrimaryPointerChanged-Ereignis von FocusProviders abonnieren, um benachrichtigt zu werden, wenn sich der primäre Zeiger im Fokus geändert hat. Dies kann äußerst nützlich sein, um zu ermitteln, ob der Benutzer derzeit mit einer Szene über Anvieren, einen 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 für -Ereignisse verwendet wird, um auf einen neuen PrimaryPointerChangedHandler primären Zeiger zu reagieren.

Primäres Zeigerbeispiel

Zeigerergebnis

Die Zeigereigenschaft enthält das aktuelle Ergebnis für die Szenenabfrage, mit der Result das Objekt mit dem Fokus bestimmt wird. Für einen Raycastzeiger, wie er standardmäßig für Bewegungscontroller, Anvisiereneingaben und Handlichtlichter erstellt wurde, enthält er die Position und den Normalwert des Raycasttreffers.

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/PointerResult/PointerResultExample.unity) zeigt, wie der Zeiger verwendet wird, um ein Objekt an der Trefferposition zu Result erstellen.

Zeigerergebnis

Deaktivieren von Zeigern

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

// 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 PointerUtils Beispiele finden Sie unter und TurnPointersOnOff .

Zeigerinteraktionen über editor

Für Zeigerereignisse, die von behandelt werden, bietet MRTK zusätzlichen Komfort in Form der -Komponente, wodurch Zeigerereignisse direkt über IMixedRealityPointerHandlerPointerHandler Unity-Ereignisse behandelt werden können.

Zeigerhandler

Zeiger-Extent

Far-Zeiger verfügen über 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 konsistent mit dem Verhalten der HoloLens zu bleiben.

Dies kann durch Aktualisieren der DefaultControllerPointer Felder der Prefab-Komponente ShellHandRayPointer geändert werden:

Zeiger-Extent: Steuert den maximalen Abstand, mit dem Zeiger interagieren.

Standardzeiger-Extent: Steuert die Länge des Zeigerstrahls/der Linie, die gerendert wird, wenn der Zeiger nicht mit etwas interagiert.

Siehe auch