XRHands 동기화

Fusion XR 프로토타이핑 애드온

이 모듈은 XR Hands의 손 상태(손가락 추적 포함)를 동기화하는 방법을 보여줍니다.

손을 표시할 수도 있습니다:

  • 수집된 컨트롤러에서 받은 데이터에서
  • 손가락 추적 데이터에서

손가락 추적 데이터와 관련하여 애드온은 대역폭 소비를 줄이기 위해 손뼈 데이터를 고도로 압축하는 방법을 보여줍니다.

손가락 동기화 데모

노트: 이 애드온은 Meta OVR 손 동기화, 와 유사하지만 OpenXR 컨텍스트(Oculus Quest, Apple Vision Pro, ...)에 해당합니다.

그러나 몇 가지 개선 사항이 포함되어 있으며 몇 가지 제스처 감지 도구도 추가되어 있습니다.

손 로직 개요

이 애드온은 컨트롤러 기반 손 추적과 손가락 기반 손 추적을 공존하게 합니다. 목표는 한 곳에서 다른 곳으로 원활하게 전환하는 것입니다.

그렇게 하려면:

  • 다른 VR 샘플과 마찬가지로 컨트롤러를 사용할 때 표시되는 손 모델은 Oculus Sample 프레임워크의 손 모델입니다.
  • 손가락 추적을 사용하면 로컬 사용자인 XRHandSkeletonDriver 컴포넌트의 하위 클래스인 XRHandCollectableSkeletonDriver를 사용하여 손과 손가락뼈 데이터를 수집하여 로컬 골격에 적용합니다. 이 골격은 로컬 전용 메시를 표시하는 데 사용할 수 있습니다(단, 기본 프리팹에서는 원격 사용자와 동일한 네트워크 버전의 핸드를 표시하기 위해 이 골격을 숨깁니다).
  • 원격 사용자의 경우, NetworkBonesStateSync 컴포넌트(아래 설명)가 네트워크에서 손과 손가락뼈 회전 데이터를 복구하여 손 골격의 변환을 이동시키고, 그 자체가 스킨 메시 렌더러에 의해 적절한 손 렌더러로 이어집니다
  • Render 중에, NetworkBonesStateSync는 수신된 두 손 상태 사이의 손뼈 회전을 매끄럽게 보간하고, 두 틱 사이에서도 매끄러운 뼈 회전을 표시하기 위해 Fusion 보간 데이터를 사용합니다.
손 로직

로컬 하드웨어 리그 손 컴포넌트

로컬 사용자 하드웨어 리그의 손 계층 아래에 위치한 XRHandCollectableSkeletonDriver 컴포넌트는 손 상태를 수집하여 동기화 컴포넌트에 제공합니다. XRHand의 부모인 XRHandSkeletonDriver 컴포넌트에 의존하여 손 상태(특히 손가락뼈 회전 포함)에 접근할 수 있으며 형제인 XRHandTrackingEvents 컴포넌트가 필요합니다.

또한 손가락 추적이 현재 사용되는지 여부를 알 수 있는 헬퍼 속성이 포함되어 있습니다.

노트: XRHandCollectableSkeletonDriver에는 아래 "네트워크 리그 손 컴포넌트"에 설명된 것처럼 손 상태 동기화에 필요한 스크립트 가능한 객체를 채우기 위해 기본 뼈 위치를 찾고 뼈 회전 압축 표현을 제안하는 분석 코드도 포함되어 있습니다. 기본 스크립트 파일은 대부분의 필요에 따라 애드온에서 제공되며, 분석 코드는 애드온에서 제공되지만 손뼈가 많이 변하지 않는 한 사용할 필요가 없습니다.

네트워크 리그 손 컴포넌트

로컬 사용자의 경우 사용자 네트워크 리그의 NetworkBonesStateSync 컴포넌트는 로컬 하드웨어 핸드에서 IBonesCollecter 인터페이스를 구현하는 컴포넌트를 찾아 로컬 핸드 상태를 찾은 다음 FixedUpdateNetwork에서 네트워크 변수에 저장합니다.

IBonesCollecter 인터페이스는 XRHandCollectableSkeletonDriver 컴포넌트에 의해 구현되며, 다음과 같습니다:

  • 손가락 추적 상태를 제공합니다
  • 손의 뼈 회전을 제공합니다.

원격 사용자의 경우 동기화된 데이터를 파싱하여 Render 중에 로컬 손 상태를 재현합니다. BonesStateScriptableObject는 네트워크를 통해 동기화된 회전 데이터 외에도 뼈의 로컬 위치를 제공합니다(결코 변하지 않습니다). 이 애드온에는 XRHand의 손에 대한 위치를 정의하는 LeftXRHandsDefaultBonesStateRightXRHandsDefaultBonesState의 에셋이 포함됩니다.

NetworkBonesStateSync는 주어진 순간에 각 뼈의 원활한 회전을 보여주기 위해 수신된 두 상태 사이의 뼈 회전을TryGetSnapshotsBuffers(out var fromBuffer, out var toBuffer, out var alpha)를 사용하여 보간과 관련된 "from" 및 "to" 뼈 회전 상태를 찾습니다.

그런 다음 이러한 손 포즈는 XRHandRemoteSkeletonDriver(XRHands의 XRHandSkeletonDriver의 하위 클래스)와 같이 IBonesReader를 구현하는 네트워크 핸드 상의 임의의 컴포넌트에 의해 로컬 골격에 적용됩니다.

마지막으로 SkinnedMeshRenderer는 이 뼈를 이용해 손을 제대로 보여줍니다.

대역폭 최적화

뼈 정보는 전송하는 데 꽤 비용이 많이 듭니다. 손 상태에는 동기화할 24개의 쿼터니온이 포함됩니다.

NetworkBonesStateSync 컴포넌트는 손 뼈의 일부 특성(특정 회전축, 제한된 이동 범위 등)을 사용하여 대역폭을 줄입니다. 각 뼈에 필요한 정밀도 수준은 전용 HandSynchronizationScriptable에서 지정할 수 있습니다.

NetworkBonesStateSynchandSynchronizationScriptable 속성에 제공되지 않으면 기본 압축이 사용되며, 이 압축은 애드온에 제공되는 LeftHandSynchronizationRightHandSynchronization 에셋에 제공되는 압축보다 효율성이 떨어집니다. 이러한 압축은 대부분의 요구 사항에 맞게 구성되었습니다:

  • 그들은 약 20배 적은 바이트를 사용하여 매우 높은 압축을 제공합니다(손 전체 뼈 회전 세트는 전체 쿼터니언 전송을 위해 386 바이트 대신 19 바이트로 저장됩니다).
  • 압축이 원격 사용자의 손가락 표현에 가시적인 영향을 미치지 않습니다.

손 모델 토글

HandRepresentationManager 컴포넌트는 현재 사용 중인 핸드 트래킹 모드를 기반으로 핸드에 대해 표시되는 메시를 처리합니다:

  • 컨트롤러 추적을 사용할 때 Oculus 샘플 프레임워크 핸드 메시를 사용합니다,
  • 또는 손가락 추적을 사용할 때 XRHandSkeletonDriver 컴포넌트 로직에 의해 애니메이션화된 뼈 골격에 의존하는 메시

이 스크립트의 두 가지 버전이 존재하는데, 하나는 로컬 하드웨어 핸드용(손 골격 애니메이션화, 콜라이더 로컬화 목적 또는 오프라인 핸드가 필요한 경우)이며, 다른 하나는 네트워크 핸드용입니다.

로컬 하드웨어 리그 핸드

이 버전은 하드웨어 핸드에 배치된 IBonesCollecter(XRHandCollectableSkeletonDriver와 같은)에 의존합니다.

또한 다른 기능 외에도 손가락 추적을 사용할 때 손바닥 위치에 국한된 것, 컨트롤러 기반 추적을 사용할 때 손바닥 위치에 국한된 것, 두 개의 잡는 콜라이더 사이를 전환해야 합니다(손의 "중심"이 두 모드에서 정확히 같은 위치에 있지 않음). 이는 두 개의 인덱스 팁 충돌기에서도 동일하게 수행됩니다.

참고: 현재 설정에서는 네트워크로 연결된 핸드만 표시하도록 선택되었습니다. 하드웨어 리그의 핸드는 뼈 위치를 수집하고 인덱스 콜라이더 위치를 적절하게 애니메이션화하기 위해 여기에 있습니다. 따라서 하드웨어 핸드에 사용되는 머티리얼은 투명합니다(컨트롤러 핸드의 경우 Android에서 필요합니다. 그렇지 않으면 렌더러를 비활성화하면 애니메이션이 뼈를 움직이지 않습니다). 하드웨어 핸드 표현 관리자의 HardwareHandRepresentationManagerMaterialOverrideModeOverride로 설정된 덕분에 overrideMaterialForRenderers 필드에 투명한 머티리얼을 제공하여 자동으로 하드웨어 핸드 메시가 투명하게 설정됩니다.

네트워크 리그 손

NetworkHandRepresentationManager 컴포넌트는 컨트롤러 추적을 사용할 때 Oculus 샘플 프레임워크 핸드 메시(손가락 추적 상태를 동기화하는 NetworkBonesStateSync 데이터에서 확인) 또는 NetworkBonesStateSync 로직에 의존하는 메시를 핸드 모드에 따라 처리합니다.

아바타 애드온

프로젝트에서 아바타 애드온 을 사용하는 경우 아바타 피부색에 따라 손 색깔을 적용하는 것도 가능합니다.

그렇게 하려면:

  • HandManagerAvatarRepresentationConnector의 두 번째 줄 #define AVATAR_ADDON_AVAILABLE의 주석을 없애고
  • NetworkHandRepresentationManager 및/또는 HardwareHandRepresentationManager 옆에 HandManagerAvatarRepresentationConnector를 배치합니다

제스처 인식

손가락 추적 데이터를 사용하는 데 도움이 되도록 손 자세를 분석하는 데 도움이 되는 일부 헬퍼 스크립트가 제공됩니다.

FingerDrivenGesture는 이 스크립트의 기본이며 OpenXR 핸드 하위 시스템과의 연결은 물론 분실된 콜백을 추적합니다.

FingerDrivenHardwareRigPose는 보통 컨트롤러 버튼(잡는지 여부를 판단하기 위해 인덱스를 가리키거나...)으로 채워진 핸드 명령을 채웁니다. 또한 꼬집거나 중지와 약지를 눌러 잡는 동작을 감지합니다(두 가지 옵션을 동시에 활성화할 수 있으며 HardwareHand에서 isGrabbing을 트리거 하는 경우는 한 번(또는 전혀 활성화되지 않음).

FingerDriverBeamer는 총을 든 자세(인덱스와 엄지만 올린 상태)를 감지해 RayBeamer를 작동시켜 순간이동 시킵니다. 활성화되면 엄지가 계속 올라가는 한(다른 손가락은 더 이상 확인되지 않음) 빔은 활성화됩니다.

FingerDrivenMenu는 사용자가 손을 잠시 쳐다볼 때 팝업을 띄울 수 있고, 손을 헤드셋 쪽으로 돌리면 메뉴가 업데이트됩니다.

Toucher 서브 클래스인 Pincher는 핀치를 감지하여 IPinchable 인터페이스를 구현하는 터치된 물체에 전달합니다. 이 물체들은 한 번의 핀치 동작으로 한 번의 핀치 동작만으로 동작을 시작했는지 확인하기 위해 TryConsumePinch로 핀치를 소모할 수 있습니다.

데모

데모 씬은 Assets\Photon\FusionAddons\XRHandsSynchronization\Demo\Scenes\ 폴더에 있습니다.

의존성

  • XRShared 애드온 2.0

다운로드

이 애드온의 최신 버전은 XR 애드온 프로젝트에 있습니다.

지원하는 토폴로지

  • 공유 모드

변경 내역

  • 버전 2.0.3: 유니티 2021.x와의 호환성 확인(박스 콜라이더, 2022.x 편집, 2021.x 열었을 때 프리팹 핸드에서 크기가 부적절함)
  • 버전 2.0.2: 정의 검사 추가(Fusion이 아직 설치되지 않은 경우 처리)
  • 버전 2.0.1: 투명 머티리얼 변경(unlit shader)
  • 버전 2.0.0: 최초 릴리즈
Back to top