상호 작용 가능 — MRTK2
Interactable
구성 요소는 모든 개체를 입력에 쉽게 상호 작용하고 응답할 수 있도록 하는 올인원 컨테이너입니다. 상호 작용 가능은 터치, 손 광선, 음성 등 모든 유형의 입력에 대한 catch-all 역할을 하며 이러한 상호 작용을 이벤트 및 시각적 테마 응답으로 유입합니다. 이 구성 요소는 단추를 만들고, 포커스가 있는 개체의 색을 변경하는 등의 쉬운 방법을 제공합니다.
Interactable을 구성하는 방법
구성 요소는 구성의 세 가지 기본 섹션을 허용합니다.
일반 입력 설정
상태
상태는 상호 작용 가능한 프로필 및 시각적 테마에 대한 누르기 또는 관찰과 같은 상호 작용 단계를 정의하는 ScriptableObject 매개 변수입니다.
DefaultInteractableStates(Assets/MRTK/SDK/Features/UX/Interactable/States/DefaultInteractableStates.asset)는 MRTK와 함께 기본적으로 제공되며 상호 작용 가능한 구성 요소의 기본 매개 변수입니다.
DefaultInteractableStates 자산은 네 가지 상태를 포함하며 상태 모델 구현을 InteractableStates
활용합니다.
기본값: 아무 작업도 수행되지 않습니다. 가장 격리된 기본 상태입니다.
포커스: 개체가 가리키고 있습니다. 이는 단일 상태이며 다른 상태는 현재 설정되어 있지 않지만 기본 순위가 지정됩니다.
누르기: 개체가 가리키고 있고 단추나 손을 누르고 있습니다. Press 상태는 기본 및 포커스의 순위를 지정합니다. 이 상태는 물리적 언론에 대한 대체로 설정됩니다.
사용 안 함: 단추는 대화형이 아니어야 하며 시각적 피드백은 어떤 이유로 이 단추를 현재 사용할 수 없는 경우 사용자에게 알립니다. 이론적으로는 사용 안 함 상태가 다른 모든 상태를 포함할 수 있지만 사용이 해제되면 사용 안 함 상태는 다른 모든 상태를 능가합니다.
목록의 순서에 따라 비트 값(#)이 상태에 할당됩니다.
참고
일반적으로 상호 작용 가능한 구성 요소를 만들 때 DefaultInteractableStates(Assets/MRTK/SDK/Features/UX/Interactable/States/DefaultInteractableStates.asset)를 활용하는 것이 좋습니다.
그러나 테마를 구동하는 데 사용할 수 있는 상호 작용 가능한 상태는 17개이지만 일부는 다른 구성 요소에 의해 구동됩니다. 기본 제공 기능이 있는 항목 목록은 다음과 같습니다.
- 방문: 상호 작용 가능 항목을 클릭했습니다.
- 토글됨: 단추가 토글된 상태이거나 차원 인덱스가 홀수입니다.
- 제스처: 손 또는 컨트롤러를 눌렀고 원래 위치에서 이동했습니다.
- VoiceCommand: 상호 작용 가능을 트리거하는 데 음성 명령이 사용되었습니다.
- PhysicalTouch: 터치 입력이 현재 검색되어 를 사용하여
NearInteractionTouchable
사용하도록 설정합니다. - 잡아: 손은 현재 개체의 범위를 잡고 있습니다. 를 사용하여
NearInteractionGrabbable
사용하도록 설정합니다.
Enabled
상호 작용 가능 개체가 사용하도록 설정되었는지 여부를 전환합니다. 코드의 에 Interactable.IsEnabled
해당합니다.
Interactable의 사용 속성은 GameObject/Component(예: SetActive 등)를 통해 구성된 사용 속성과 다릅니다. GameObject 또는 상호 작용 가능한 MonoBehaviour를 사용하지 않도록 설정하면 입력, 시각적 테마, 이벤트 등을 포함하여 클래스의 모든 항목이 실행되지 않도록 설정됩니다. 를 통해 Interactable.IsEnabled
사용하지 않도록 설정하면 대부분의 입력 처리가 비활성화되어 관련 입력 상태가 다시 설정됩니다. 그러나 클래스는 여전히 모든 프레임을 실행하고 무시되는 입력 이벤트를 받습니다. 이는 Visual 테마를 통해 수행할 수 있는 사용 안 함 상태로 Interactable을 표시하는 데 유용합니다. 일반적인 예로 필요한 모든 입력 필드가 완료될 때까지 기다리는 제출 단추가 있습니다.
입력 작업
상호 작용 가능 구성 요소가 반응해야 하는 입력 구성 또는 컨트롤러 매핑 프로필에서 입력 작업을 선택합니다.
이 속성은 를 통해 Interactable.InputAction
코드에서 런타임에 구성할 수 있습니다.
IsGlobal
true이면 선택한 입력 작업에 대한 전역 입력 수신기로 구성 요소를 표시 합니다. 기본 동작은 false이며 이 상호 작용 가능한 충돌기/GameObject로만 입력을 제한합니다.
이 속성은 를 통해 Interactable.IsGlobal
코드에서 런타임에 구성할 수 있습니다.
Speech 명령
음성 상호 작용을 위한 OnClick 이벤트를 트리거하기 위한 MRTK Speech 명령 프로필의 음성 명령입니다.
이 속성은 를 통해 Interactable.VoiceCommand
코드에서 런타임에 구성할 수 있습니다.
포커스 필요
true이면 음성 명령은 포인터에서 포커스가 이미 있는 경우에만 Interactable 을 활성화합니다. false이면 Interactable 이 선택한 음성 명령에 대한 전역 수신기 역할을 합니다. 여러 전역 음성 수신기가 장면에서 구성하기 어려울 수 있으므로 기본 동작은 true입니다.
이 속성은 를 통해 Interactable.VoiceRequiresFocus
코드에서 런타임에 구성할 수 있습니다.
선택 모드
이 속성은 선택 논리를 정의합니다.
Interactable을 클릭하면 다음 차원 수준으로 반복됩니다.
차원은 순위와 유사하며 입력 외부의 상태(예: 포커스, 누르기 등)를 정의합니다. 단추와 연결된 토글 상태 또는 기타 다중 순위 상태를 정의하는 데 유용합니다. 현재 차원 수준은 에 의해 Interactable.DimensionIndex
추적됩니다.
사용 가능한 선택 모드는 다음과 같습니다.
- 단추 - 차원 = 1, 간단한 클릭 가능한 상호 작용 가능
- 토글 - 차원 = 2, 오프/상태 간의상호 작용 가능한 대체
- 다차원 - 차원>= 3을 클릭하면 현재 차원 수준 + 1이 증가합니다. 목록 등에 단추 상태를 정의하는 데 유용합니다.
상호 작용 가능 을 사용하면 차원당 여러 테마를 정의할 수도 있습니다. 예를 들어 SelectionMode=Toggle을 사용하면Interactable 이 선택 취소 될 때 하나의 테마가 적용되고 구성 요소를 선택할 때 다른 테마가 적용될 수 있습니다.
현재 선택 모드는 를 통해 Interactable.ButtonMode
런타임에 쿼리할 수 있습니다. 런타임 시 모드를 업데이트하려면 속성을 원하는 기능과 일치하도록 설정 Interactable.Dimensions
하여 수행할 수 있습니다. 또한 토글 및 다차원 모드에 유용한 현재 차원은 를 통해 Interactable.CurrentDimension
액세스할 수 있습니다.
상호 작용 가능한 프로필
프로필은 GameObject와 시각적 테마 간에 관계를 만드는 항목입니다. 프로필은 상태 변경이 발생할 때 테마에서 조작할 콘텐츠를 정의합니다.
테마는 재료와 매우 유사합니다. 현재 상태에 따라 개체에 할당될 속성 목록을 포함하는 스크립팅 가능한 개체입니다. 테마도 다시 사용할 수 있으며 여러 상호 작용 가능한 UX 개체에 할당할 수 있습니다.
삭제할 때 다시 설정
시각적 테마는 선택한 테마 엔진의 클래스 및 유형에 따라 대상 GameObject의 다양한 속성을 수정합니다. 상호 작용 가능 구성 요소가 제거될 때 삭제 시 다시 설정 이 true이면 구성 요소는 수정된 모든 속성을 활성 테마에서 원래 값으로 다시 설정합니다. 그렇지 않으면 제거될 때 상호 작용 가능 구성 요소는 수정된 속성을 그대로 둡니다. 이 후자의 경우 다른 외부 구성 요소에 의해 변경되지 않는 한 값의 마지막 상태가 유지됩니다. 기본값은 false입니다.
이벤트
모든 상호 작용 가능 구성 요소에는 구성 요소가 단순히 선택될 때 발생하는 OnClick 이벤트가 있습니다. 그러나 상호 작용 가능 을 사용하여 OnClick 이외의 입력 이벤트를 검색할 수 있습니다.
이벤트 추가 단추를 클릭하여 새 유형의 이벤트 수신기 정의를 추가합니다. 추가되면 원하는 이벤트 유형을 선택합니다.
)
다양한 유형의 입력에 응답하는 다양한 유형의 이벤트 수신기가 있습니다. MRTK는 다음 수신기 세트와 함께 제공됩니다.
InteractableAudioReceiver
InteractableOnClickReceiver
InteractableOnFocusReceiver
InteractableOnGrabReceiver
InteractableOnHoldReceiver
InteractableOnPressReceiver
InteractableOnToggleReceiver
InteractableOnTouchReceiver
를 확장하는 새 클래스를 만들어 사용자 지정 수신기를 만들 수 있습니다 ReceiverBase
.
토글 이벤트 수신기의 예
상호 작용 가능한 수신기
InteractableReceiver
구성 요소를 사용하면 이벤트가 원본 상호 작용 가능 구성 요소 외부에서 정의될 수 있습니다.
InteractableReceiver는 다른 Interactable에서 발생한 필터링된 이벤트 유형을 수신 대기합니다.
Interactable 속성이 직접 할당되지 않은 경우 검색 범위 속성은 InteractableReceiver가 자체, 부모 또는 자식 GameObject에 있는 이벤트를 수신 대기하는 방향을 정의합니다.
InteractableReceiverList
는 비슷한 방식으로 작동하지만 일치하는 이벤트 목록에 대해 작동합니다.
사용자 지정 이벤트 만들기
시각적 테마와 마찬가지로 이벤트를 확장하여 상태 패턴을 감지하거나 기능을 노출할 수 있습니다.
사용자 지정 이벤트는 두 가지 기본 방법으로 만들 수 있습니다.
클래스를
ReceiverBase
확장하여 이벤트 유형의 드롭다운 목록에 표시되는 사용자 지정 이벤트를 만듭니다. Unity 이벤트는 기본적으로 제공되지만 추가 Unity 이벤트를 추가하거나 이벤트를 설정하여 Unity 이벤트를 숨길 수 있습니다. 이 기능을 사용하면 디자이너가 프로젝트에서 엔지니어와 협력하여 디자이너가 편집기에서 설정할 수 있는 사용자 지정 이벤트를 만들 수 있습니다.클래스를
ReceiverBaseMonoBehavior
확장하여 Interactable 또는 다른 개체에 상주할 수 있는 완전히 사용자 지정 이벤트 구성 요소를 만듭니다. 는ReceiverBaseMonoBehavior
상호 작용 가능 을 참조하여 상태 변경을 검색합니다.
확장의 예 ReceiverBase
클래스는 CustomInteractablesReceiver
Interactable에 대한 상태 정보를 표시하며 사용자 지정 이벤트 수신기를 만드는 방법의 예입니다.
public CustomInteractablesReceiver(UnityEvent ev) : base(ev, "CustomEvent")
{
HideUnityEvents = true; // hides Unity events in the receiver - meant to be code only
}
다음 메서드는 사용자 지정 이벤트 수신기를 만들 때 재정의/구현하는 데 유용합니다.
ReceiverBase.OnUpdate()
는 상태 패턴/전환을 검색하는 데 사용할 수 있는 추상 메서드입니다. 또한 ReceiverBase.OnVoiceCommand()
및 ReceiverBase.OnClick()
메서드는 Interactable 을 선택할 때 사용자 지정 이벤트 논리를 만드는 데 유용합니다.
public override void OnUpdate(InteractableStates state, Interactable source)
{
if (state.CurrentState() != lastState)
{
// the state has changed, do something new
lastState = state.CurrentState();
...
}
}
public virtual void OnVoiceCommand(InteractableStates state, Interactable source,
string command, int index = 0, int length = 1)
{
base.OnVoiceCommand(state, source, command, index, length);
// voice command called, perform some action
}
public virtual void OnClick(InteractableStates state,
Interactable source,
IMixedRealityPointer pointer = null)
{
base.OnClick(state, source);
// click called, perform some action
}
검사기에서 사용자 지정 이벤트 수신기 필드 표시
ReceiverBase 스크립트는 특성을 사용하여 InspectorField
검사기에서 사용자 지정 속성을 노출합니다. 다음은 도구 설명 및 레이블 정보가 있는 사용자 지정 속성인 Vector3의 예입니다. 이 속성은 상호 작용 가능한 GameObject가 선택되고 연결된 이벤트 수신기 유형이 추가될 때 검사기에서 구성 가능한 것으로 표시됩니다.
[InspectorField(Label = "<Property label>",Tooltip = "<Insert tooltip info>",Type = InspectorField.FieldTypes.Vector3)]
public Vector3 EffectOffset = Vector3.zero;
상호 작용 가능을 사용하는 방법
간단한 단추 빌드
입력 이벤트를 받도록 구성된 GameObject에 상호 작용 가능 구성 요소를 추가하여 간단한 단추를 만들 수 있습니다. 그것은 그것에 또는 입력을 받을 아이에 충돌자를 가질 수 있습니다. Unity UI 기반 GameObjects와 상호 작용 가능 을 사용하는 경우 Canvas GameObject 아래에 있어야 합니다.
새 프로필을 만들고, GameObject 자체를 할당하고, 새 테마를 만들어 단추를 한 단계 더 진행합니다. 또한 OnClick 이벤트를 사용하여 작업을 수행합니다.
참고
단추를 누를 수 있도록 하려면 구성 요소가 필요합니다PressableButton
.
PhysicalPressEventRouter
또한 구성 요소는 상호 작용 가능 구성 요소로 프레스 이벤트를 깔때기하는 데 필요합니다.
토글 및 다차원 단추 만들기
토글 단추
토글 가능 단추를 만들려면 필드를 형식Toggle
으로 변경 Selection Mode
합니다.
프로필 섹션에서 상호 작용 가능을 전환할 때 사용되는 각 프로필에 대해 새 토글된 테마가 추가됩니다.
이 SelectionMode
토글로 설정된 동안 IsToggled 검사 상자를 사용하여 런타임 초기화 시 컨트롤의 기본값을 설정할 수 있습니다.
CanSelect는 상호 작용 가능 개체가 꺼져 있고 CanDeselect는 역을 의미합니다.
개발자는 및 IsToggled
인터페이스를 SetToggled
활용하여 코드를 통해 Interactable의 토글 상태를 가져오기/설정할 수 있습니다.
// If using SelectionMode = Toggle (i.e Dimensions == 2)
// Make the Interactable selected and toggled on
myInteractable.IsToggled = true;
// Get whether the Interactable is selected or not
bool isSelected = myInteractable.IsToggled;
단추 컬렉션 설정/해제
방사형 집합 또는 라디오 단추 등이라고도 하는 지정된 시간에 하나만 활성화할 수 있는 토글 단추 목록이 있는 것이 일반적입니다.
InteractableToggleCollection
구성 요소를 사용하여 이 기능을 사용하도록 설정합니다. 이 컨트롤은 지정된 시간에 하나의 상호 작용 가능 만 켜지도록 합니다.
RadialSet(Assets/MRTK/SDK/Features/UX/Interactable/Prefabs/RadialSet.prefab)도 훌륭한 시작점입니다.
사용자 지정 방사형 단추 그룹을 만들려면 다음을 수행합니다.
- 여러 상호 작용 가능한 GameObjects/buttons 만들기
- SelectionMode = Toggle, CanSelect = true 및 CanDeselect = false를 사용하여 상호 작용 가능한 각 설정
- 모든 Interactable 에 대해 빈 부모 GameObject를 만들고 InteractableToggleCollection 구성 요소를 추가합니다.
- InteractableToggleCollection의 ToggleList에 모든 Interactable 추가
- InteractableToggleCollection.CurrentIndex 속성을 설정하여 시작 시 기본적으로 선택된 단추를 결정합니다.
다차원 단추
다차원 선택 모드는 순차적 단추 또는 빠른(1x), 빠른(2x) 또는 가장 빠른(3x) 값으로 속도 제어와 같이 두 단계가 넘는 단추를 만드는 데 사용됩니다.
차원이 숫자 값인 경우 각 단계에 대해 다른 테마를 사용하여 각 속도 설정에 대한 단추의 텍스트 레이블 또는 질감을 제어하기 위해 최대 9개의 테마를 추가할 수 있습니다.
모든 클릭 이벤트는 값에 도달할 때까지 런타임에 1씩 Dimensions
진행 DimensionIndex
됩니다. 그러면 주기가 0으로 다시 설정됩니다.
개발자는 를 DimensionIndex
평가하여 현재 활성 상태인 차원을 확인할 수 있습니다.
// If using SelectionMode = Multi-dimension (i.e Dimensions >= 3)
//Access the current DimensionIndex
int currentDimension = myInteractable.CurrentDimension;
//Set the current DimensionIndex to 2
myInteractable.CurrentDimension = 2;
// Promote Dimension to next level
myInteractable.IncreaseDimension();
런타임에 상호 작용 가능 만들기
상호 작용 가능 은 런타임에 모든 GameObject에 쉽게 추가할 수 있습니다. 다음 예제에서는 시각적 테마를 사용하여 프로필을 할당하는 방법을 보여 줍니다.
var interactableObject = GameObject.CreatePrimitive(PrimitiveType.Cylinder);
var interactable = interactableObject.AddComponent<Interactable>();
// Get the default configuration for the Theme engine InteractableColorTheme
var newThemeType = ThemeDefinition.GetDefaultThemeDefinition<InteractableColorTheme>().Value;
// Define a color for every state in our Default Interactable States
newThemeType.StateProperties[0].Values = new List<ThemePropertyValue>()
{
new ThemePropertyValue() { Color = Color.black}, // Default
new ThemePropertyValue() { Color = Color.black}, // Focus
new ThemePropertyValue() { Color = Random.ColorHSV()}, // Pressed
new ThemePropertyValue() { Color = Color.black}, // Disabled
};
interactable.Profiles = new List<InteractableProfileItem>()
{
new InteractableProfileItem()
{
Themes = new List<Theme>()
{
Interactable.GetDefaultThemeAsset(new List<ThemeDefinition>() { newThemeType })
},
Target = interactableObject,
},
};
// Force the Interactable to be clicked
interactable.TriggerOnClick()
코드를 통한 상호 작용 가능한 이벤트
다음 예제와 함께 코드를 통해 기본 Interactable.OnClick
이벤트에 작업을 추가할 수 있습니다.
public static void AddOnClick(Interactable interactable)
{
interactable.OnClick.AddListener(() => Debug.Log("Interactable clicked"));
}
함수를 Interactable.AddReceiver<T>()
사용하여 런타임에 이벤트 수신기를 동적으로 추가합니다.
아래 예제 코드에서는 포커스 입력/종료를 수신 대기하는 InteractableOnFocusReceiver를 추가하고 이벤트 인스턴스가 발생할 때 수행할 작업 코드를 정의하는 방법을 보여 줍니다.
public static void AddFocusEvents(Interactable interactable)
{
var onFocusReceiver = interactable.AddReceiver<InteractableOnFocusReceiver>();
onFocusReceiver.OnFocusOn.AddListener(() => Debug.Log("Focus on"));
onFocusReceiver.OnFocusOff.AddListener(() => Debug.Log("Focus off"));
}
아래 예제 코드에서는 토글 가능 Interactables에서 선택/선택 취소된 상태 전환을 수신 대기하고 이벤트 인스턴스가 실행될 때 수행할 작업 코드를 정의하는 InteractableOnToggleReceiver를 추가하는 방법을 보여 줍니다.
public static void AddToggleEvents(Interactable interactable)
{
var toggleReceiver = interactable.AddReceiver<InteractableOnToggleReceiver>();
// Make the interactable have toggle capability, from code.
// In the gui editor it's much easier
interactable.Dimensions = 2;
interactable.CanSelect = true;
interactable.CanDeselect = true;
toggleReceiver.OnSelect.AddListener(() => Debug.Log("Toggle selected"));
toggleReceiver.OnDeselect.AddListener(() => Debug.Log("Toggle un-selected"));
}