Zeiger — MRTK2
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 MixedRealityPointerProfile
konfiguriert. 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.
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.
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 IMixedRealityPointer
Skript 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 BaseControllerPointer
verwendet wird. Um den Cursor programmgesteuert zu ändern, ändern Sie die BaseCursor
-Eigenschaft für das entsprechende IMixedRealityPointer
Verhalten.
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.
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.
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 LinePointer
erweitert 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.
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.
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 ManipulationHandler
nü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.
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.
- 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.
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.
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.
- Das MRTK-Eingabesystem erkennt, dass ein Eingabeereignis aufgetreten ist.
- Das MRTK-Eingabesystem löst die relevante Schnittstellenfunktion für das Eingabeereignis für alle registrierten globalen Eingabehandler aus.
- Das Eingabesystem bestimmt, welches GameObject für den Zeiger im Fokus steht, der das Ereignis ausgelöst hat.
- Das Eingabesystem verwendet das Ereignissystem von Unity , um die relevante Schnittstellenfunktion für alle übereinstimmenden Komponenten auf dem fokussierten GameObject auszulösen.
- 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.
- Beispiel: Komponenten, die die Schnittstelle
- 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.
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.
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 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 Beispiele finden Sie PointerUtils
unter und TurnPointersOnOff
.
Zeigerinteraktionen über den Editor
Für Zeigerereignisse, die von IMixedRealityPointerHandler
behandelt werden, bietet MRTK weitere Annehmlichkeiten in Form der PointerHandler
-Komponente, die es ermöglicht, Zeigerereignisse direkt über Unity-Ereignisse zu behandeln.
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.