手部追蹤 — MRTK2
手部追蹤設定檔
[手部追蹤] 設定檔位於[輸入系統] 設定檔下。 其中包含自訂手部標記法的設定。
聯合預製專案
使用簡單預製專案將聯合預製專案視覺化。 「手掌」和「索引指」聯結具有特殊重要性,而且擁有自己的預製專案,而所有其他聯合則共用相同的預製專案。
根據預設,手部接合預製專案是簡單的幾何基本類型。 如有需要,可以取代這些專案。 如果未指定預製專案,則會改為建立空 的 GameObjects 。
警告
請避免在聯合預製專案中使用複雜的腳本或昂貴的轉譯,因為聯結物件會在每一個畫面上轉換,而且可能會有顯著的效能成本!
預設手部聯合標記法 | 聯合標籤 |
---|---|
手部網格預製專案
如果手部追蹤裝置提供完整定義的網格資料,則會使用手部網格。 預製物件中可轉譯的網格會由來自裝置的資料取代,因此立方體之類的虛擬網格就已足夠。 預製專案材質用於手部網格。
手部網格顯示器可能會有明顯的效能影響,因此可以取消核取 [ 啟用手部網格視覺效果 ] 選項來完全停用。
手部視覺效果設定
可以分別透過 [手部網格視覺效果模式] 設定和 [手部聯合視覺效果模式] 設定來關閉或開啟手部網格和手部聯合視覺效果。 這些設定是應用程式模式特定的,這表示在編輯器 (中開啟某些功能,以查看與編輯器內模擬的聯結,例如,在部署到播放機組建中的裝置 (時,) 同時關閉相同的功能) 。
請注意,通常建議在編輯器 (中開啟手部聯合視覺效果,讓編輯器內模擬顯示手部接合) 的位置,以及讓手部聯合視覺效果和手部網格視覺效果在玩家 (關閉,因為它們會產生效能點擊) 。
指令碼
每個個別手部接合都可以從輸入系統要求位置和旋轉。 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
會保留一組 持續性的 GameObjects 來追蹤聯合。
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 Native
目前使用 .NET 後端的主要組建有已知問題。 在.NET Native中, IInspectable
指標無法使用 從原生封送處理到 Managed 程式碼 Marshal.GetObjectForIUnknown
。 MRTK 會使用此來取得 SpatialCoordinateSystem
,以便從平臺接收手部和眼睛資料。
我們已在原生Mixed Reality工具組存放庫中,提供 DLL 來源作為此問題的因應措施。 請遵循讀我檔案中的指示,並將產生的二進位檔複製到 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;
}
}