次の方法で共有


ハンド トラッキング — MRTK2

手追跡プロファイル

ハンド トラッキング プロファイル、入力システム プロファイルの下にあります。 これには、手の表現をカスタマイズするための設定が含まれています。

ハンド トラッキング プロファイル

ジョイント プレハブ

ジョイント プレハブは、単純なプレハブを使用して視覚化されます。 手のひらジョイントと人差し指ジョイントは特別に重要であり、独自のプレハブを持ち、他のすべてのジョイントは同じプレハブを共有します。

既定では、ハンド ジョイント プレハブは単純なジオメトリ プリミティブです。 これらは必要に応じて置き換えることができます。 プレハブがまったく指定されていない場合は、代わりに空 の GameObject が 作成されます。

警告

ジョイント オブジェクトはフレームごとに変換されるため、ジョイント プレハブでは複雑なスクリプトや高価なレンダリングを使用しないでください。これは、パフォーマンスコストが大きくなる可能性があるためです。

既定の手関節表現 ジョイント ラベル
多関節ハンドジョイント 入力ハンド ジョイント

ハンドメッシュプレハブ

ハンド メッシュは、完全に定義されたメッシュ データがハンド トラッキング デバイスによって提供される場合に使用されます。 プレハブでレンダリング可能なメッシュはデバイスからのデータに置き換えられるので、キューブなどのダミー メッシュで十分です。 プレハブの素材はハンドメッシュに使用されます。

入力ハンド メッシュ

ハンド メッシュの表示はパフォーマンスに大きな影響を与える可能性があるため、[ ハンド メッシュの視覚化を有効にする] オプションをオフにすることで完全に無効にすることができます。

手の視覚エフェクトの設定

ハンド メッシュとハンド ジョイントの視覚エフェクトは、それぞれ [ ハンド メッシュの視覚化モード ] 設定と [ ハンド ジョイントの視覚化モード ] を使用してオフまたはオンにすることができます。 これらの設定はアプリケーション モード固有です。つまり、(プレーヤー ビルドで) デバイスに展開するときに同じ機能をオフにしたまま、エディター内で一部の機能をオンにすることができます (たとえば、エディター内のシミュレーションでジョイントを表示する)。

一般に、エディターでハンド ジョイントの視覚化を有効にすることをお勧めします (エディター内シミュレーションでハンド ジョイントの場所が表示されるようにするため)。また、プレイヤーでハンド ジョイントの視覚化とハンド メッシュの視覚化をオフにすることをお勧めします (パフォーマンス ヒットが発生するため)。

スクリプト

位置および回転は MixedRealityPoseとして個々の手の接合箇所のための入力システムから要求することができる。

または、ジョイントに続く GameObject への アクセスがシステムによって許可されます。 これは、別の GameObject がジョイントを継続的に追跡する必要がある場合に便利です。

使用可能なジョイントは、 TrackedHandJoint 列挙型に一覧表示されます。

注:

手の追跡が失われると、ジョイントオブジェクトが破壊されます! ジョイント オブジェクトを使用するすべてのスクリプトが、エラーを回避するために null ケースを適切に処理することを確認します。

特定のハンド コントローラーへのアクセス

特定のハンド コントローラーは、入力イベントを処理する場合など、多くの場合に使用できます。 この場合、 IMixedRealityHand インターフェイスを使用して、デバイスから直接共同データを要求できます。

コントローラーから共同ポーズをポーリングする

TryGetJoint関数は、何らかの理由で要求されたジョイントが使用できない場合、falseを返します。 その場合、結果のポーズが MixedRealityPose.ZeroIdentityされます。

public void OnSourceDetected(SourceStateEventData eventData)
{
  var hand = eventData.Controller as IMixedRealityHand;
  if (hand != null)
  {
    if (hand.TryGetJoint(TrackedHandJoint.IndexTip, out MixedRealityPose jointPose)
    {
      // ...
    }
  }
}

手のビジュアライザーからのジョイント変換

ジョイント オブジェクトは、 コントローラー ビジュアライザーから要求できます。

public void OnSourceDetected(SourceStateEventData eventData)
{
  var handVisualizer = eventData.Controller.Visualizer as IMixedRealityHandVisualizer;
  if (handVisualizer != null)
  {
    if (handVisualizer.TryGetJointTransform(TrackedHandJoint.IndexTip, out Transform jointTransform)
    {
      // ...
    }
  }
}

簡単なジョイント データ アクセス

特定のコントローラーが指定されていない場合、ユーティリティ クラスが提供され、ハンド ジョイント データに簡単にアクセスできます。 これらの関数は、現在追跡されている最初の使用可能なハンド デバイスから共同データを要求します。

HandJointUtils からジョイント ポーズをポーリングする

HandJointUtils は、最初のアクティブなハンド デバイスに対してクエリを実行する静的クラスです。

if (HandJointUtils.TryGetJointPose(TrackedHandJoint.IndexTip, Handedness.Right, out MixedRealityPose pose))
{
    // ...
}

ハンドジョイントサービスからのジョイント変形

IMixedRealityHandJointService は、ジョイントを追跡するための 永続的な GameObject の セットを保持します。

var handJointService = CoreServices.GetInputSystemDataProvider<IMixedRealityHandJointService>();
if (handJointService != null)
{
    Transform jointTransform = handJointService.RequestJointTransform(TrackedHandJoint.IndexTip, Handedness.Right);
    // ...
}

ハンド トラッキング イベント

コントローラーからデータを直接ポーリングすることが望ましくない場合は、入力システムもイベントを提供します。

共同イベント

IMixedRealityHandJointHandler は、ジョイント位置の更新を処理します。

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))
            {
                // ...
            }
        }
    }
}

メッシュ イベント

IMixedRealityHandMeshHandler は、多関節ハンド メッシュの変更を処理します。

ハンド メッシュは既定では有効になっていないことに注意してください。

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;
            }

            // ...
        }
    }
}

既知の問題

.NET ネイティブ

現在、.NET バックエンドを使用したマスター ビルドには既知の問題があります。 .NET ネイティブでは、Marshal.GetObjectForIUnknownを使用して、IInspectable ポインターをネイティブからマネージド コードにマーシャリングすることはできません。 MRTK はこれを使用して、プラットフォームから手と目のデータを受信するために SpatialCoordinateSystem を取得します。

ネイティブ Mixed Reality Toolkit リポジトリで、この問題の回避策として DLL ソースを提供しました。 README の指示に従って、結果のバイナリをUnityアセットの Plugins フォルダーにコピーしてください。 その後、MRTK で提供されている WindowsMixedRealityUtilities スクリプトによって回避策が解決されます。

独自の DLL を作成する場合、または既存の DLL にこの回避策を含める場合、回避策の中心は次のとおりです。

extern "C" __declspec(dllexport) void __stdcall MarshalIInspectable(IUnknown* nativePtr, IUnknown** inspectable)
{
    *inspectable = nativePtr;
}

C# Unity コードでの使用:

[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;
    }
}