손 추적 - MRTK2
손 추적 프로필
손 추적 프로필은 입력 시스템 프로필 아래에 있습니다. 여기에는 손 표현을 사용자 지정하기 위한 설정이 포함되어 있습니다.
![손 추적 프로필](../images/input/handtrackingprofile.png?view=mrtkunity-2022-05)
조인트 프리팹
조인트 프리팹은 간단한 프리팹을 사용하여 시각화됩니다. 손바닥과 검지 손가락 관절은 특별한 중요성과 자신의 프리팹을 가지고, 다른 모든 관절은 동일한 프리팹을 공유하는 동안.
기본적으로 손 관절 프리팹은 간단한 기하학적 기본 형식입니다. 원하는 경우 바꿀 수 있습니다. 프리팹을 전혀 지정하지 않으면 빈 GameObjects 가 대신 만들어집니다.
경고
조인트 개체는 모든 프레임에서 변환되고 성능 비용이 많이 들 수 있으므로 복잡한 스크립트를 사용하거나 공동 프리팹에서 비용이 많이 드는 렌더링을 사용하지 마세요.
기본 손 관절 표현 | 공동 레이블 |
---|---|
![]() |
![]() |
손 메시 프리팹
손 메시는 손 추적 디바이스에서 완전히 정의된 메시 데이터를 제공하는 경우에 사용됩니다. 프리팹에서 렌더링 가능한 메시는 디바이스의 데이터로 대체되므로 큐브와 같은 더미 메시로 충분합니다. 프리팹의 재질은 손 메시에 사용됩니다.
![입력 손 메시](../images/input-simulation/mrtk_core_input_hands_articulatedhandmesh.png?view=mrtkunity-2022-05)
손 메시 디스플레이는 성능에 큰 영향을 미칠 수 있으므로 손 메시 시각화 사용 옵션을 선택 취소하여 완전히 사용하지 않도록 설정할 수 있습니다.
손 시각화 설정
손 메시 및 손 관절 시각화는 각각 손 메시 시각화 모드 설정 및 손 관절 시각화 모드 를 통해 끄거나 끌 수 있습니다. 이러한 설정은 애플리케이션 모드에 따라 다릅니다. 즉, 편집기에서 일부 기능을 켜고(예: 편집기 내 시뮬레이션과의 조인트 보기) 디바이스에 배포할 때(플레이어 빌드에서) 동일한 기능을 해제할 수 있습니다.
일반적으로 편집기에서 손 관절 시각화를 켜고(편집기 내 시뮬레이션에서 손 관절이 있는 위치를 표시하도록) 플레이어에서 손 관절 시각화와 손 메시 시각화를 모두 해제하는 것이 좋습니다(성능이 저하되기 때문).
스크립팅
각 개별 손 관절에 대한 입력 시스템에서 위치 및 회전을 로 MixedRealityPose
요청할 수 있습니다.
또는 시스템에서 관절을 따르는 GameObjects에 액세스할 수 있습니다. 이는 다른 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 네이티브
현재 .NET 백 엔드를 사용하는 마스터 빌드에 알려진 문제가 있습니다. .NET 네이티브 IInspectable
포인터는 를 사용하여 Marshal.GetObjectForIUnknown
네이티브에서 관리 코드로 마샬링할 수 없습니다. MRTK는 이를 사용하여 플랫폼에서 손 및 눈 데이터를 수신하기 위해 를 가져옵니다 SpatialCoordinateSystem
.
네이티브 Mixed Reality Toolkit 리포지토리에서 이 문제에 대한 해결 방법으로 DLL 원본을 제공했습니다. 추가 정보 지침에 따라 결과 이진 파일을 Unity 자산의 플러그 인 폴더에 복사하세요. 그런 다음 MRTK에 제공된 WindowsMixedRealityUtilities 스크립트가 해결 방법을 resolve.
고유한 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;
}
}