컨트롤러, 포인터 및 포커스 — MRTK2

컨트롤러, 포인터 및 포커스는 핵심 입력 시스템에 의해 설정된 기초를 기반으로 하는 상위 수준 개념입니다. 함께 장면의 개체와 상호 작용하기 위한 메커니즘의 상당 부분을 제공합니다.

Controllers

컨트롤러는 물리적 컨트롤러의 표현입니다(자유도 6도, 관절 손 등). 디바이스 관리자는 디바이스 관리자에 의해 생성되며 해당 기본 시스템과 통신하고 해당 데이터를 MRTK 모양의 데이터 및 이벤트로 변환할 책임이 있습니다.a

예를 들어 Windows Mixed Reality 플랫폼에서 WindowsMixedRealityArticulatedHand 는 기본 Windows 손 추적 API와 상호 작용하여 손의 관절, 포즈 및 기타 속성에 대한 정보를 가져오는 컨트롤러입니다. 이 데이터를 관련 MRTK 이벤트(예: RaisePoseInputChanged 또는 RaiseHandJointsUpdated 호출)로 전환하고 쿼리가 올바른 데이터를 반환할 수 있도록 TryGetJointPose 자체 내부 상태를 업데이트해야 합니다.

일반적으로 컨트롤러의 수명 주기에는 다음이 포함됩니다.

  1. 컨트롤러는 새 원본을 검색할 때 디바이스 관리자에 의해 만들어집니다(예: 디바이스 관리자가 손 추적을 감지하고 시작).

  2. 컨트롤러의 Update() 루프에서 기본 API 시스템을 호출합니다.

  3. 동일한 업데이트 루프에서 핵심 입력 시스템 자체(예: HandMeshUpdated 또는 HandJointsUpdated 발생)로 직접 호출하여 입력 이벤트 변경 내용을 발생합니다.

포인터 및 포커스

포인터는 게임 개체와 상호 작용하는 데 사용됩니다. 이 섹션에서는 포인터를 만드는 방법, 포인터를 업데이트하는 방법 및 포커스가 있는 개체를 결정하는 방법에 대해 설명합니다. 또한 존재하는 다양한 유형의 포인터와 활성 상태인 시나리오를 다룹니다.

포인터 범주

포인터는 일반적으로 다음 범주 중 하나에 속합니다.

  • 원거리 포인터

    이러한 유형의 포인터는 사용자와 멀리 떨어져 있는 개체와 상호 작용하는 데 사용됩니다(멀리 떨어져 있는 개체는 단순히 "가까이 있지 않음"으로 정의됨). 이러한 유형의 포인터는 일반적으로 전 세계로 이동하여 사용자가 바로 옆에 있지 않은 개체와 상호 작용하고 조작할 수 있는 선을 캐스팅합니다.

  • 근거리 포인터

    이러한 유형의 포인터는 사용자가 잡고 터치하고 조작할 수 있을 만큼 가까운 개체와 상호 작용하는 데 사용됩니다. 일반적으로 이러한 유형의 포인터는 근처의 개체를 찾아서 개체와 상호 작용합니다(작은 거리에서 레이캐스팅을 수행하거나, 주변 개체를 찾는 구형 캐스팅을 수행하거나, 잡기 가능/터치 가능으로 간주되는 개체 목록을 열거).

  • 텔레포트 포인터

    이러한 유형의 포인터는 텔레포트 시스템에 연결하여 포인터가 대상으로 하는 위치로 사용자 이동을 처리합니다.

포인터 조정

단일 컨트롤러에는 여러 포인터가 있을 수 있으므로(예: 조인된 손은 근거리 및 원거리 상호 작용 포인터를 둘 다 가질 수 있음) 활성 상태여야 하는 포인터를 중재하는 구성 요소가 있습니다.

예를 들어 사용자의 손이 누를 수 있는 단추에 접근하면 표시를 ShellHandRayPointer 중지하고 PokePointer 참여해야 합니다.

이는 모든 포인터의 DefaultPointerMediator상태에 따라 활성 상태인 포인터를 결정하는 역할을 하는 에 의해 처리됩니다. 이 작업을 수행하는 주요 작업 중 하나는 가까운 포인터가 개체에 가까운 경우 원거리 포인터를 사용하지 않도록 설정하는 것입니다(참조 DefaultPointerMediator하세요).

포인터 프로필의 속성을 변경하여 포인터 중재자의 대체 구현을 PointerMediator 제공할 수 있습니다.

포인터를 사용하지 않도록 설정하는 방법

포인터 중재자는 모든 프레임을 실행하므로 모든 포인터의 활성/비활성 상태를 제어하게 됩니다. 따라서 코드에서 포인터의 IsInteractionEnabled 속성을 설정하면 포인터 중재자가 모든 프레임을 덮어씁니다. 대신 포인터를 PointerBehavior 직접 켜거나 끌지 여부를 제어하도록 지정할 수 있습니다. 이는 기본값 FocusProviderDefaultPointerMediator MRTK를 사용하는 경우에만 작동합니다.

예: MRTK에서 손 광선 사용 안 함

다음 코드는 MRTK에서 손 광선을 끕니다.

// Turn off all hand rays
PointerUtils.SetHandRayPointerBehavior(PointerBehavior.AlwaysOff);

// Turn off hand rays for the right hand only
PointerUtils.SetHandRayPointerBehavior(PointerBehavior.AlwaysOff, Handedness.Right);

다음 코드는 MRTK의 기본 동작에 손 광선을 반환합니다.

PointerUtils.SetHandRayPointerBehavior(PointerBehavior.Default);

다음 코드는 잡기 가능 항목에 가까운지와 관계없이 손 광선이 켜지도록 합니다.

// Turn off all hand rays
PointerUtils.SetHandRayPointerBehavior(PointerBehavior.AlwaysOn);

자세한 예제를 TurnPointersOnOff 참조 PointerUtils 하세요.

FocusProvider

모든 FocusProvider 포인터 목록을 반복하고 각 포인터에 대해 포커스가 있는 개체가 무엇인지 파악하는 일을 담당합니다.

Update() 호출에서 다음이 수행됩니다.

  1. 포인터 자체에 의해 구성된 대로 광선 캐스팅 및 적중 감지를 수행하여 모든 포인터를 업데이트합니다(예: 구 포인터는 SphereOverlap raycastMode를 지정할 수 있으므로 FocusProvider는 구 기반 충돌을 수행합니다.)

  2. 포인터별로 포커스가 있는 개체를 업데이트합니다(즉, 개체가 포커스를 얻은 경우 해당 개체에 대한 이벤트도 트리거됩니다. 개체가 포커스를 분실한 경우 포커스 손실 등을 트리거함).

포인터 구성 및 수명 주기

포인터는 입력 시스템 프로필의 포인터 섹션에서 구성할 수 있습니다.

포인터의 수명은 일반적으로 다음과 같습니다.

  1. 디바이스 관리자는 컨트롤러의 존재를 감지합니다. 그러면 이 디바이스 관리자가 호출 RequestPointers을 통해 컨트롤러와 연결된 포인터 집합을 만듭니다.

  2. FocusProvider는 Update() 루프에서 모든 유효한 포인터를 반복하고 연결된 레이캐스트 또는 적중 검색 논리를 수행합니다. 각 특정 포인터에 포커스가 있는 개체를 결정하는 데 사용됩니다.

    • 동시에 활성화된 입력 원본이 여러 개 있을 수 있으므로(예: 두 손이 활성 상태인 경우) 동시에 포커스가 있는 여러 개체가 있을 수도 있습니다.
  3. 디바이스 관리자는 컨트롤러 원본이 손실되었음을 발견하면 손실된 컨트롤러와 연결된 포인터를 삭제합니다.