Zeiger — MRTK2
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.
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.
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.
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.
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.

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 LinePointer
erweitert, 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.
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.

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.

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

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.

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.
- Das MRTK-Eingabesystem erkennt ein Eingabeereignis.
- Das MRTK-Eingabesystem löst die relevante Schnittstellenfunktion für das Eingabeereignis auf alle registrierten globalen Eingabehandler aus.
- Das Eingabesystem bestimmt, welche GameObject im Fokus für den Zeiger steht, der das Ereignis ausgelöst hat.
- Das Eingabesystem verwendet das Unity-Ereignissystem , um die relevante Schnittstellenfunktion für alle übereinstimmenden Komponenten auf dem fokussierten GameObject zu auslösen.
- 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.
- Beispiel: Komponenten, die die Schnittstelle
- 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.

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.

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 IMixedRealityPointerHandler
MRTK behandelt werden, bietet MRTK weitere Komfort in Form der PointerHandler
Komponente, wodurch Zeigerereignisse direkt über Unity-Ereignisse behandelt werden können.

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.