Handverfolgung – MRTK2
Handverfolgungsprofil
Das Profil "Handverfolgung" befindet sich unter dem Profil "Eingabesystem". Es enthält Einstellungen zum Anpassen der Handdarstellung.
Gemeinsame Prefabs
Gemeinsame Prefabs werden mithilfe einfacher Prefabs visualisiert. Die Hand- und Zeigefingergelenke sind von besonderer Bedeutung und haben ein eigenes Prefab, während alle anderen Gelenke das gleiche Prefab teilen.
Standardmäßig sind die Handgelenk-Prefabs einfache geometrische Grundtypen. Diese können bei Bedarf ersetzt werden. Wenn überhaupt kein Prefab angegeben ist, werden stattdessen leere GameObjects erstellt.
Warnung
Vermeiden Sie die Verwendung komplexer Skripts oder teurer Renderings in gemeinsamen Prefabs, da gemeinsame Objekte auf jedem Frame transformiert werden und erhebliche Leistungskosten verursachen können!
Standardhandgelenkdarstellung | Gelenkbezeichnungen |
---|---|
Handgitter-Prefab
Das Handgitter wird verwendet, wenn vollständig definierte Gitterdaten vom Handverfolgungsgerät bereitgestellt werden. Das im Prefab renderbare Gitter wird durch Daten des Geräts ersetzt, sodass ein Dummy-Gitter wie ein Würfel ausreichend ist. Das Material des Prefabs wird für das Handgitter verwendet.
Die Handgitteranzeige kann spürbare Auswirkungen auf die Leistung haben. Aus diesem Grund kann sie vollständig deaktiviert werden, indem Sie die Option Handgittervisualisierung aktivieren deaktivieren.
Einstellungen für die Handvisualisierung
Die Handgitter- und Handgelenkvisualisierungen können über die Einstellungen Hand mesh Visualization Modes bzw . Hand Joint Visualization Modes (Handgittervisualisierungsmodi ) deaktiviert oder aktiviert werden. Diese Einstellungen sind anwendungsmodusspezifisch, d. h., es ist möglich, einige Features im Editor zu aktivieren (um z. B. Gelenke mit der Simulation im Editor zu sehen), während dieselben Features deaktiviert sind, wenn sie auf dem Gerät bereitgestellt werden (in Playerbuilds).
Beachten Sie, dass es im Allgemeinen empfohlen wird, die Handgelenkvisualisierung im Editor zu aktivieren (damit die Im-Editor-Simulation zeigt, wo sich die Handgelenke befinden), und sowohl die Handgelenkvisualisierung als auch die Handgittervisualisierung im Spieler deaktivieren zu lassen (weil sie einen Leistungstreffer verursachen).
Skripterstellung
Position und Drehung können vom Eingabesystem für jedes einzelne Handgelenk als MixedRealityPose
angefordert werden.
Alternativ ermöglicht das System den Zugriff auf GameObjects , die den Gelenken folgen. Dies kann nützlich sein, wenn ein anderes GameObject ein Gelenk kontinuierlich nachverfolgen soll.
Verfügbare Gelenke sind in der TrackedHandJoint
Enumeration aufgeführt.
Hinweis
Gemeinsame Objekte werden zerstört, wenn die Handverfolgung verloren geht! Stellen Sie sicher, dass alle Skripts, die das gemeinsame Objekt verwenden, den null
Fall ordnungsgemäß behandeln, um Fehler zu vermeiden!
Zugreifen auf einen bestimmten Handcontroller
Ein bestimmter Handcontroller ist häufig verfügbar, z. B. bei der Verarbeitung von Eingabeereignissen. In diesem Fall können die gemeinsamen Daten direkt über die Schnittstelle vom Gerät IMixedRealityHand
angefordert werden.
Abfragen der gemeinsamen Pose vom Controller
Die TryGetJoint
Funktion gibt zurück false
, wenn das angeforderte Gelenk aus irgendeinem Grund nicht verfügbar ist. In diesem Fall lautet MixedRealityPose.ZeroIdentity
die resultierende Pose .
public void OnSourceDetected(SourceStateEventData eventData)
{
var hand = eventData.Controller as IMixedRealityHand;
if (hand != null)
{
if (hand.TryGetJoint(TrackedHandJoint.IndexTip, out MixedRealityPose jointPose)
{
// ...
}
}
}
Gemeinsame Transformation aus der Handschnellansicht
Gemeinsame Objekte können über die Controllerschnellansicht angefordert werden.
public void OnSourceDetected(SourceStateEventData eventData)
{
var handVisualizer = eventData.Controller.Visualizer as IMixedRealityHandVisualizer;
if (handVisualizer != null)
{
if (handVisualizer.TryGetJointTransform(TrackedHandJoint.IndexTip, out Transform jointTransform)
{
// ...
}
}
}
Vereinfachter gemeinsamer Datenzugriff
Wenn kein spezifischer Controller angegeben wird, werden Hilfsklassen für den bequemen Zugriff auf Handgelenkdaten bereitgestellt. Diese Funktionen fordern gemeinsame Daten vom ersten verfügbaren Handgerät an, das derzeit nachverfolgt wird.
Abfragen der gemeinsamen Pose von HandJointUtils
HandJointUtils
ist eine statische Klasse, die das erste aktive Gerät abfragt.
if (HandJointUtils.TryGetJointPose(TrackedHandJoint.IndexTip, Handedness.Right, out MixedRealityPose pose))
{
// ...
}
Gemeinsame Transformation aus dem handgelenkten Dienst
IMixedRealityHandJointService
behält einen persistenten Satz von GameObjects zum Nachverfolgen von Gelenken bei.
var handJointService = CoreServices.GetInputSystemDataProvider<IMixedRealityHandJointService>();
if (handJointService != null)
{
Transform jointTransform = handJointService.RequestJointTransform(TrackedHandJoint.IndexTip, Handedness.Right);
// ...
}
Handverfolgungsereignisse
Das Eingabesystem stellt auch Ereignisse bereit, wenn das direkte Abfragen von Daten von Controllern nicht wünschenswert ist.
Gemeinsame Veranstaltungen
IMixedRealityHandJointHandler
behandelt Aktualisierungen von gemeinsamen Positionen.
public class MyHandJointEventHandler : IMixedRealityHandJointHandler
{
public Handedness myHandedness;
void IMixedRealityHandJointHandler.OnHandJointsUpdated(InputEventData<IDictionary<TrackedHandJoint, MixedRealityPose>> eventData)
{
if (eventData.Handedness == myHandedness)
{
if (eventData.InputData.TryGetValue(TrackedHandJoint.IndexTip, out MixedRealityPose pose))
{
// ...
}
}
}
}
Mesh-Ereignisse
IMixedRealityHandMeshHandler
behandelt Änderungen des handgelenkten Handgitters.
Beachten Sie, dass Handgitter standardmäßig nicht aktiviert sind.
public class MyHandMeshEventHandler : IMixedRealityHandMeshHandler
{
public Handedness myHandedness;
public Mesh myMesh;
public void OnHandMeshUpdated(InputEventData<HandMeshInfo> eventData)
{
if (eventData.Handedness == myHandedness)
{
myMesh.vertices = eventData.InputData.vertices;
myMesh.normals = eventData.InputData.normals;
myMesh.triangles = eventData.InputData.triangles;
if (eventData.InputData.uvs != null && eventData.InputData.uvs.Length > 0)
{
myMesh.uv = eventData.InputData.uvs;
}
// ...
}
}
}
Bekannte Probleme
.NET systemeigen
Es gibt derzeit ein bekanntes Problem mit Masterbuilds, die das .NET-Back-End verwenden. In .NET Native IInspectable
können Zeiger nicht mithilfe Marshal.GetObjectForIUnknown
von nativem in verwalteten Code gemarshallt werden. MRTK verwendet diese, um die SpatialCoordinateSystem
zu erhalten, um Hand- und Augendaten von der Plattform zu erhalten.
Wir haben eine DLL-Quelle als Problemumgehung für dieses Problem im nativen repository Mixed Reality Toolkit bereitgestellt. Befolgen Sie die Anweisungen in der Infodatei, und kopieren Sie die resultierenden Binärdateien in einen Plug-In-Ordner in Ihren Unity-Ressourcen. Danach löst das im MRTK bereitgestellte Skript WindowsMixedRealityUtilities die Problemumgehung für Sie auf.
Wenn Sie Eine eigene DLL erstellen oder diese Problemumgehung in eine vorhandene dll einschließen möchten, ist der Kern der Problemumgehung:
extern "C" __declspec(dllexport) void __stdcall MarshalIInspectable(IUnknown* nativePtr, IUnknown** inspectable)
{
*inspectable = nativePtr;
}
Und seine Verwendung in Ihrem C#-Unity-Code:
[DllImport("DotNetNativeWorkaround.dll", EntryPoint = "MarshalIInspectable")]
private static extern void GetSpatialCoordinateSystem(IntPtr nativePtr, out SpatialCoordinateSystem coordinateSystem);
private static SpatialCoordinateSystem GetSpatialCoordinateSystem(IntPtr nativePtr)
{
try
{
GetSpatialCoordinateSystem(nativePtr, out SpatialCoordinateSystem coordinateSystem);
return coordinateSystem;
}
catch
{
UnityEngine.Debug.LogError("Call to the DotNetNativeWorkaround plug-in failed. The plug-in is required for correct behavior when using .NET Native compilation");
return Marshal.GetObjectForIUnknown(nativePtr) as SpatialCoordinateSystem;
}
}