Share via


Handverfolgung – MRTK2

Handverfolgungsprofil

Das Profil "Handverfolgung" befindet sich unter dem Profil "Eingabesystem". Es enthält Einstellungen zum Anpassen der Handdarstellung.

Handverfolgungsprofil

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
Gelenke der Hand Eingabehandgelenke

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.

Eingabehandgitter

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 MixedRealityPoseangefordert 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.ZeroIdentitydie 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.GetObjectForIUnknownvon 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;
    }
}