Zeiger — MRTK2

Zeiger

In diesem Artikel wird erläutert, wie Sie Zeigereingaben in der Praxis konfigurieren und darauf reagieren. Informationen zum Steuern mehrerer Zeiger auf allgemeiner Ebene finden Sie unter Zeigerarchitektur.

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

Zeigerkonfiguration

Zeiger werden als Teil des Eingabesystems in MRTK über einen MixedRealityPointerProfilekonfiguriert. Dieser Typ von Profil wird einem MixedRealityInputSystemProfile im MRTK-Konfigurationsinspektor zugewiesen. Das Zeigerprofil bestimmt den Cursor, die Zur Laufzeit verfügbaren Zeigertypen und die Kommunikation dieser Zeiger untereinander, um zu entscheiden, welche Zeiger aktiv sind.

  • Zeigeausdehnung : Definiert die maximale Entfernung, für die ein Zeiger mit einem GameObject interagieren kann.

  • Zeigende Raycast-Ebenenmasken: Dies ist ein priorisiertes Array von LayerMasks, um zu bestimmen, mit welchen möglichen GameObjects ein beliebiger Zeiger interagieren kann, und die Reihenfolge der Interaktion, die versucht werden soll. Dies kann nützlich sein, um sicherzustellen, dass Zeiger zuerst vor anderen Szenenobjekten mit Ui-Elementen interagieren. Zeigerprofilbeispiel

Konfiguration der Zeigeroptionen

Die STANDARDMÄßIGE MRTK-Zeigerprofilkonfiguration umfasst die folgenden Zeigerklassen und die zugeordneten Vorabeinstellungen. Die Liste der Zeiger, die dem System zur Laufzeit zur Verfügung stehen, ist im Zeigerprofil unter Zeigeroptionen 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 Das Zeigeroptionenprofil

Jeder Zeigereintrag wird durch den folgenden Datensatz definiert:

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

    • Der PokePointer ist beispielsweise für das "Stochern" von Objekten mit einem Finger verantwortlich und ist standardmäßig als unterstützungsfähig für den Artikulierten Handcontrollertyp gekennzeichnet. Zeiger werden nur instanziiert, wenn ein Controller verfügbar wird und insbesondere der Controllertyp definiert, mit welchen Controllern dieses Zeiger-Prefab erstellt werden kann.
  • Händigkeit – ermöglicht es einem Zeiger, nur für eine bestimmte Hand (links/rechts) instanziiert zu werden.

Hinweis

Wenn Sie die Eigenschaft Handedness eines Zeigereintrags auf Keine festlegen, wird sie effektiv aus dem System deaktiviert, als Alternative zum Entfernen des Zeigers aus der Liste.

  • Zeiger prefab : Dieses Prefab-Asset wird instanziiert, wenn ein Controller, der dem angegebenen Controllertyp entspricht, und die Händigkeit beginnt, nachverfolgt zu werden.

Es ist möglich, dass einem Controller mehrere Zeiger zugeordnet sind. Beispielsweise ist in DefaultHoloLens2InputSystemProfile (Assets/MRTK/SDK/Profiles/HoloLens2/) der Gelenkhandcontroller dem PokePointer, GrabPointer und dem DefaultControllerPointer (d. h. Handstrahlen) zugeordnet.

Hinweis

MRTK bietet eine Reihe von Zeiger-Prefabs in Assets/MRTK/SDK/Features/UX/Prefabs/Zeiger. Ein neues benutzerdefiniertes Prefab kann erstellt werden, solange es eines der Zeigerskripts in Assets/MRTK/SDK/Features/UX/Scripts/Zeiger oder ein anderes implementierende IMixedRealityPointerSkript enthält.

Cursorkonfiguration

Der Gaze-Cursor 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 das prefab ändern, das CursorPrefab im Feld des entsprechenden BaseControllerPointerverwendet wird. Um den Cursor programmgesteuert zu ändern, ändern Sie die BaseCursor -Eigenschaft für das entsprechende IMixedRealityPointer Verhalten.

Cursor Prefab-Eigenschaft

Beispiele für Implementierungen des Cursorverhaltens finden Sie unter Assets/MRTK/SDK/Features/UX/Prefabs/Cursors . Insbesondere bietet der DefaultGazeCursor eine robuste Implementierung zum Ändern der Grafik des Cursors basierend auf dem kontextbezogenen Zustand.

Standardzeigerklassen

Die folgenden Klassen sind die sofort einsatzbereiten MRTK-Zeiger, die im oben beschriebenen MRTK-Standardzeigerprofil verfügbar und definiert sind. Jedes unter Assets/MRTK/SDK/Features/UX/Prefabs/Zeiger bereitgestellte Zeiger-Prefab enthält eine der angefügten Zeigerkomponenten.

MRTK-Standardzeiger

Fernzeiger

LinePointer

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

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

MRTK-Zeigerlinie
CurvePointer

CurvePointer erweitert die LinePointer-Klasse , indem es mehrere Strahlumläufe entlang einer Kurve zulässt. Diese Basiszeigerklasse ist nützlich für gekrümmte Instanzen wie Teleportationszeiger, bei denen die Linie konsistent in eine Parabel gekrümmt wird.

ShellHandRayPointer

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

GGVPointer

Der GGVPointer wird auch als Blick-/Geste/Stimme-Zeiger (GGV) bezeichnet und unterstützt HoloLens 1-Style-Look- und Tap-Interaktionen, hauptsächlich über Gaze und Air Tap oder Gaze and Voice Select-Interaktion. 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-Eingaben (d. h. Touchscreen) verantwortlich. Dies sind "Ferninteraktionen", da das Berühren des Bildschirms einen Strahl von der Kamera an einen potenziell weit entfernten Ort in der Szene wirft.

MousePointer

Der MousePointer schaltet einen Bildschirm für weit entfernte Interaktionen in die Welt, aber für Maus statt Touch.

Mauszeiger

Hinweis

Die Mausunterstützung ist in MRTK standardmäßig nicht verfügbar, kann jedoch aktiviert werden, indem dem MRTK-Eingabeprofil ein neuer Eingabedatenanbieter vom Typ MouseDeviceManager hinzugefügt und dem MixedRealityMouseInputProfile Datenanbieter zugewiesen wird.

Nahzeiger

PokePointer

Der PokePointer wird verwendet, um mit Spielobjekten zu interagieren, die "Nahinteraktion touchable" unterstützen. dabei handelt es sich um GameObjects, die über ein angefügtes NearInteractionTouchable Skript verfügen. Im Fall von UnityUI sucht dieser Zeiger nach NearInteractionTouchableUnityUIs. Der PokePointer verwendet einen SphereCast, um das nächstgelegene anfassbare Element zu bestimmen, und wird verwendet, um Dinge wie die druckbaren Tasten zu bewegen.

Stellen Sie beim Konfigurieren des GameObject mit der NearInteractionTouchable -Komponente sicher, dass sie den localForward-Parameter so konfigurieren, dass er von der Vorderseite der Schaltfläche oder einem anderen Objekt aus verweist, das touchierbar gemacht werden soll. Stellen Sie außerdem sicher, dass die Grenzen des Touchables mit den Grenzen des touchierbaren Objekts übereinstimmen.

Nützliche Poke-Zeigereigenschaften:

  • TouchableDistance: Maximale Entfernung, in der eine anfassbare Oberfläche interagiert werden kann
  • Visuals: Spielobjekt, das zum Rendern von Fingerspitzen (standardmäßig der Ring am Finger) verwendet wird.
  • Linie: Optionale Linie, um von der Fingerspitze auf die aktive Eingabeoberfläche zu zeichnen.
  • Poke 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 NearInteractionTouchable Komponente verfügen muss, um mit einem Poke-Zeiger interagieren zu können.
Poke-Zeiger
SpherePointer

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

Zeiger zum Greifen

Nützliche Kugelzeigereigenschaften:

  • Kugelumwandlungsradius: Der Radius für die Kugel, die zum Abfragen nach greifbaren Objekten verwendet wird.
  • Naher Objektrand: Der Abstand oben auf dem Kugelumwandungsradius, um zu ermitteln, ob sich ein Objekt in der Nähe des Zeigers befindet. Total Near Object detection radius is Sphere Cast Radius + Near Object Margin
  • Nahe Objektsektorwinkel: Der Winkel um die Vorderachse des Zeigers zum Abfragen von objekten in der Nähe. Macht die IsNearObject Abfragefunktion wie ein Kegel. Dies ist standardmäßig auf 66 Grad festgelegt, um dem Hololens 2-Verhalten zu entsprechen.

Kugelzeiger, der so geändert wurde, dass nur Objekte in Vorwärtsrichtung abgefragt werden

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

    Hinweis

    Die Spatial Awareness-Schicht ist im standardmäßigen GrabPointer-Prefab deaktiviert, das von MRTK bereitgestellt wird. Dies geschieht, um die Auswirkungen auf die Leistung der Ausführung einer Kugelüberlappungsabfrage mit dem räumlichen Gitter zu verringern. 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-Objekt finden. Dies kann versehentliche Greifer verhindern und ermöglicht das Einschalten von Handstrahlen, wenn Sie sich möglicherweise in der Nähe eines Greifbares sind, es 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 halben Bildschirmhöhe (oder vertikalen FOV) entspricht.
Kugelzeiger

Teleportzeiger

  • TeleportPointer löst eine Teleportanforderung aus, wenn eine Aktion ausgeführt wird (d. h. die Teleporttaste wird gedrückt), um den Benutzer zu bewegen.
  • ParabolicTeleportPointer löst eine Teleportanforderung aus, wenn eine Aktion ausgeführt wird (d. h. die Teleporttaste wird gedrückt) mit einem parabolischen Linienstrahlcast, um den Benutzer zu bewegen.
Zeiger parabolisch

Zeigerunterstützung für Mixed Reality-Plattformen

In der folgenden Tabelle sind die Zeigertypen aufgeführt, die normalerweise 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ö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 Collider zugewiesen sind, empfangen Zeigerinteraktionsereignisse, wie von der zugehörigen Schnittstelle definiert.

Ereignis BESCHREIBUNG Handler
Vor Dem Ändern des Fokus/Änderung des Fokus Wird sowohl für das Spielobjekt ausgelöst, das den Fokus verliert, als auch auf das Objekt, das es jedes Mal erhält, wenn ein Zeiger den Fokus ändert. IMixedRealityFocusChangedHandler
Fokus eingabetaste/beenden Wird auf das Spielobjekt ausgelöst, das den Fokus erhält, wenn der erste Zeiger in es eingeht, und auf den, der den Fokus verliert, wenn der letzte Zeiger ihn verlässt. IMixedRealityFocusHandler
Zeiger nach unten / Gezogen / Nach oben / Geklickt Wird zum Drücken, Ziehen und Loslassen des Berichtszeigers ausgelöst. IMixedRealityPointerHandler
Toucheingabe gestartet/Aktualisiert/Abgeschlossen Wird von berührungsfähigen Zeigern ausgelöst, z. B PokePointer . zum Melden von Touchaktivitäten. 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 das Empfangen von Ereignissen basierend auf dem Fokus nicht (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 erkannt und behandelt wie normale Eingabeereignisse. Der Unterschied ist, dass Zeigereingabeereignisse nur vom GameObject im Fokus von dem Zeiger behandelt werden, der das Eingabeereignis ausgelöst hat, sowie von allen globalen Eingabehandlern. 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 löst die relevante Schnittstellenfunktion für das Eingabeereignis für alle registrierten globalen Eingabehandler aus.
  3. Das Eingabesystem bestimmt, welches GameObject für den Zeiger im Fokus steht, der das Ereignis ausgelöst hat.
    1. Das Eingabesystem verwendet das Ereignissystem von Unity , um die relevante Schnittstellenfunktion für alle übereinstimmenden Komponenten auf dem fokussierten GameObject auszulösen.
    2. Wenn zu irgendeinem Zeitpunkt ein Eingabeereignis als verwendet markiert wurde, wird der Prozess beendet, und es werden keine weiteren GameObjects-Rückrufe empfangen.
      • Beispiel: Komponenten, die die Schnittstelle IMixedRealityFocusHandler implementieren, werden nach einem GameObject-Objekt gesucht, das den Fokus gewinnt oder verliert.
      • Hinweis: Das Unity-Ereignissystem wird angezeigt, um das übergeordnete GameObject zu durchsuchen, wenn im aktuellen GameObject keine Komponenten gefunden werden, die der gewünschten Schnittstelle entsprechen.
  4. Wenn keine globalen Eingabehandler registriert sind und kein GameObject mit einer übereinstimmenden Komponente/Schnittstelle gefunden wird, ruft das Eingabesystem alle fallback-registrierten Eingabehandler auf.

Beispiel

Im Folgenden finden Sie ein Beispielskript, das die Farbe des angefügten Renderers ändert, wenn ein Zeiger den Fokus annimmt 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;
    }
}

Abfragezeiger

Es ist möglich, alle derzeit aktiven Zeiger zu erfassen, indem sie die verfügbaren Eingabequellen (d. h. verfügbare Controller und Eingaben) durchlaufen, um zu ermitteln, 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 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 erkennen, ob der Benutzer derzeit mit einer Szene über den Blick oder 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 PrimaryPointerChangedHandler für Ereignisse verwenden, um auf einen neuen primären Zeiger zu reagieren.

Beispiel für primären Zeiger

Zeigerergebnis

Die Zeigereigenschaft Result enthält das aktuelle Ergebnis für die Szenenabfrage, die verwendet wird, um das Objekt mit Fokus zu bestimmen. Für einen Raycastzeiger, wie er standardmäßig für Bewegungscontroller, Blickeingaben und Handstrahlen erstellt wurde, enthält er die Position und die Normalität 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 Sie den Zeiger Result verwenden, um ein Objekt an der Trefferposition zu erzeugen.

Zeigerergebnis

Deaktivieren von Zeigern

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

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

Zeigerinteraktionen über den Editor

Für Zeigerereignisse, die von IMixedRealityPointerHandlerbehandelt werden, bietet MRTK weitere Annehmlichkeiten in Form der PointerHandler -Komponente, die es ermöglicht, Zeigerereignisse direkt über Unity-Ereignisse zu behandeln.

Zeigerhandler

Zeigerausdehnung

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 mit dem Verhalten der HoloLens-Shell konsistent zu bleiben.

Dies kann durch Aktualisieren der Felder der DefaultControllerPointer Komponente des ShellHandRayPointer Prefabs geändert werden:

Zeigerausdehnung : Hiermit wird der maximale Abstand gesteuert, mit dem Zeiger interagieren.

Standardzeigerausdehnung : Hiermit wird die Länge des Zeigerstrahls bzw. der Zeigerlinie gesteuert, die gerendert wird, wenn der Zeiger mit nichts interagiert.

Weitere Informationen