Version: 2022.2
언어: 한국어
이벤트 디스패치
이벤트 합성 및 전송

이벤트 처리

UI 툴킷의 이벤트는 HTML 이벤트와 유사합니다.이벤트가 발생하면 타겟 시각적 요소와 시각적 요소 트리의 전파 경로 내에 있는 모든 요소로 전송됩니다.

이벤트 처리 시퀀스는 다음과 같습니다.

  1. 루트 요소에서 이벤트 타겟의 부모까지 요소에 대한 이벤트 콜백을 실행합니다. 이는 디스패치 프로세스의 트리클다운 단계입니다.
  2. 이벤트 타겟에 대한 이벤트 콜백을 실행합니다. 이는 디스패치 프로세스의 타겟 단계입니다.
  3. 이벤트 타겟에서 ExecuteDefaultActionAtTarget()을 호출합니다.
  4. 이벤트 타겟 부모에서 루트까지 요소에 대한 이벤트 콜백을 실행합니다. 이는 디스패치 프로세스의 버블업 단계입니다.
  5. 이벤트 타겟에서 ExecuteDefaultAction()을 호출합니다.

이벤트가 전파 경로를 따라 이동하면 Event.currentTarget 프로퍼티가 현재 이벤트를 처리하는 요소에 업데이트됩니다. 이벤트 콜백 함수 내에서:

  • Event.currentTarget은 콜백이 등록되는 시각적 요소입니다.
  • Event.target은 원본 이벤트가 발생하는 시각적 요소입니다.

자세한 내용은 디스패치 이벤트를 참조하십시오.

이벤트 콜백 등록

이벤트 콜백을 등록하여 기존 클래스의 개별 인스턴스 행동(예: 텍스트 레이블에 대한 마우스 클릭에 응답)을 커스터마이즈할 수 있습니다.

전파 경로를 따라 전달되는 각 요소(타겟 제외)는 다음과 같이 하나의 이벤트를 두 번 수신할 수 있습니다.

  • 트리클다운 단계에서 한 번
  • 버블업 단계에서 한 번

기본적으로, 등록된 콜백은 타겟 단계 및 버블업 단계 동안 실행됩니다.이러한 기본 동작은 부모 요소가 자식 요소 이후에 반응하도록 합니다.

한편, 부모 요소가 자식보다 먼저 반응하도록 하려면 TrickleDown.TrickleDown 옵션을 사용하여 콜백을 등록합니다.

using UnityEngine;
using UnityEngine.UIElements;

...
VisualElement myElement = new VisualElement();

// Register a callback for the trickle-down phase.
myElement.RegisterCallback<MouseDownEvent>(MyCallback, TrickleDown.TrickleDown);
...

이는 디스패처에 타겟 단계와 트리클다운 단계에서 콜백을 실행하라고 알립니다.

커스텀 동작을 특정 시각적 요소에 추가하려면 해당 요소에 이벤트 콜백을 등록합니다.

다음 예시에서는 MouseDownEvent에 대한 콜백을 등록합니다.

// Register a callback on a mouse down event
myElement.RegisterCallback<MouseDownEvent>(MyCallback);

콜백 함수의 서명은 다음과 같습니다.

void MyCallback(MouseDownEvent evt) { /* ... */ }

하나의 이벤트에 대해 여러 개의 콜백을 등록할 수 있습니다.그러나 동일한 이벤트 및 전파 단계에 동일한 콜백 함수를 한 번만 등록할 수 있습니다.

VisualElement에서 콜백을 제거하려면 myElement.UnregisterCallback() 메서드를 호출하십시오.

이벤트 콜백에 커스텀 데이터 전송

콜백과 함께 커스텀 데이터를 이벤트로 전송할 수 있습니다. 커스텀 데이터를 부착하려면 호출을 연장하여 콜백을 등록해야 합니다.

다음 예시에서는 MouseDownEvent에 대한 콜백을 등록하고 커스텀 데이터를 콜백 함수로 보냅니다.

// Send user data along to the callback
myElement.RegisterCallback<MouseDownEvent, MyType>(MyCallbackWithData, myData);

콜백 함수의 서명은 다음과 같습니다.

void MyCallbackWithData(MouseDownEvent evt, MyType data) { /* ... */ }

값 변경 수신

UI 컨트롤은 value 프로퍼티를 사용하여 내부 상태에 대한 데이터를 보유할 수 있습니다.예제:

  • ToggleToggle이 켜지거나 꺼질 때 변경되는 부울 값을 보유합니다.
  • IntegerField는 필드의 값을 보유하는 정수를 보유합니다.

다음을 통해 컨트롤의 값을 얻을 수 있습니다.

  • 컨트롤에서 직접 값을 가져옵니다.int val = myIntegerField.value;. 컨트롤이 전송한 ChangeEvent를 수신하고 변경 사항이 발생하면 처리합니다.다음과 같이 콜백을 이벤트에 등록해야 합니다.

    //RegisterValueChangedCallback is a shortcut for RegisterCallback<ChangeEvent>.
    //It constrains the right type of T for any VisualElement that implements an 
    //INotifyValueChange interface.
    myIntegerField.RegisterValueChangedCallback(OnIntegerFieldChange);
    

    콜백 함수의 서명은 다음과 같습니다.

    void OnIntegerFieldChange(ChangeEvent<int> evt) { /* ...*/ }
    

다음을 통해 컨트롤의 값을 변경할 수 있습니다.

  • value 변수를 직접 변경합니다.myControl.value = myNewValue;.이렇게 하면 새 ChangeEvent를 트리거하게 됩니다.
  • myControl.SetValueWithoutNotify(myNewValue);를 사용합니다.이렇게 하면 새 ChangeEvent를 트리거하지 않습니다.

자세한 내용은 이벤트 변경을 참조하십시오.

컨트롤에 대한 입력 이벤트 처리

이벤트 핸들러를 사용하거나 매니퓰레이터를 사용하여 입력 이벤트를 처리할 수 있습니다.

포인터 캡처

포인터 입력을 처리할 때 컨트롤이 포인터를 캡처하기를 원할 수 있습니다.시각적 요소가 포인터를 캡처하면 Unity는 포인터가 시각적 요소 위에 있는지와 관계없이 포인터와 관련된 모든 이벤트를 시각적 요소로 전송합니다.예를 들어 드래그 이벤트를 수신하고 포인터를 캡처하는 컨트롤을 생성하면 포인터 위치와 관계없이 컨트롤이 드래그 이벤트를 계속 수신합니다.

포인터를 캡처하려면 캡처 이벤트를 사용하십시오.예시는 커스텀 에디터 창 내에 드래그 앤 드롭 UI 만들기를 참조하십시오.

매니퓰레이터를 사용하여 이벤트 처리

이벤트 로직을 UI 코드에서 분리하려면 매니퓰레이터를 사용하여 이벤트를 처리하십시오.매니퓰레이터는 이벤트 콜백을 저장하고 등록하고 등록 취소하는 전용 클래스입니다.UI 툴킷이 지원하는 매니퓰레이터 중 하나를 사용하거나 상속하여 이벤트를 처리할 수 있습니다.

UI 툴킷은 다음 매니퓰레이터를 지원합니다.

매니퓰레이터 다음에서 상속 설명
Manipulator 제공된 모든 매니퓰레이터의 기본 클래스입니다.
KeyboardNavigationManipulator Manipulator 기기별 입력 이벤트를 키보드를 사용하여 상위 레벨의 탐색 작업으로 변환합니다.
MouseManipulator Manipulator 마우스 입력을 처리합니다.활성화 필터 리스트가 있습니다.
ContextualMenuManipulator MouseManipulator 사용자가 오른쪽 클릭하거나 키보드의 메뉴 키를 누르면 컨텍스트 메뉴가 표시됩니다.
PointerManipulator MouseManipulator 포인터 입력을 처리합니다.활성화 필터 리스트가 있습니다.
Clickable PointerManipulator 요소에서 마우스 이벤트를 추적하고 사용자가 포인터를 요소 위에 올려놓은 상태에서 마우스 버튼을 클릭하면 콜백합니다.

커스텀 컨트롤로 이벤트에 응답

커스텀 컨트롤을 구현하는 경우, 다음 두 가지 방법으로 UI 툴킷 이벤트에 응답할 수 있습니다.

  • 이벤트 콜백 등록
  • 기본 액션 구현

이벤트에 대한 응답 방식은 상황에 따라 달라집니다.

콜백과 기본 액션 간의 차이는 다음과 같습니다.

  • 콜백은 클래스의 인스턴스에 등록해야 합니다. 기본 액션은 클래스에서 가상 함수로 실행됩니다.
  • 콜백은 전파 경로를 따라 모든 가상 요소에 대해 실행됩니다. 기본 액션은 이벤트 타겟에 대해서만 실행됩니다.
  • 콜백은 이벤트에 응답해야 하는지 정하기 위해 추가 확인을 수행할 수 있습니다. 예를 들어, 마우스 클릭을 처리하는 콜백이 요소가 이벤트의 타겟인지 확인할 수 있습니다. 기본 액션은 이 단계를 건너뛸 수 있습니다.
  • 기본 액션은 전파 단계 중 콜백 레지스트리 룩업이 필요하지 않으므로, 성능 측면에서 약간 유리합니다.

기본 액션 구현

기본 액션은 클래스의 모든 인스턴스에 적용됩니다. 기본 액션을 구현하는 클래스는 해당 인스턴스에 등록된 콜백도 보유할 수 있습니다.

클래스는 기본 액션을 구현할 때 VisualElement의 새로운 서브 클래스를 파생하고, ExecuteDefaultActionAtTarget() 메서드 또는 ExecuteDefaultAction() 메서드, 또는 두 메서드 모두를 구현해야 합니다.

기본 액션은 시각적 요소 서브 클래스의 각 인스턴스가 이벤트를 수신하면 해당 이벤트에서 실행됩니다. 아래 예제처럼 ExecuteDefaultActionAtTarget()ExecuteDefaultAction()을 오버라이드하여 기본 액션을 커스터마이즈할 수 있습니다.

override void ExecuteDefaultActionAtTarget(EventBase evt)
{
    // Call the base function.
    base.ExecuteDefaultActionAtTarget(evt);

    if (evt.eventTypeId == MouseDownEvent.TypeId())
    {
        // ...
    }
    else if (evt.eventTypeId == MouseUpEvent.TypeId())
    {
        // ...
    }
    // More event types
}

ExecuteDefaultAction()에서 기본 액션을 구현하면 기본 액션의 실행을 중지하거나 막을 수 있습니다.

타겟 기본 액션이 부모 콜백 전에 실행되도록 만들고 싶으면 ExecuteDefaultActionAtTarget()에서 기본 액션을 구현하십시오.

기본 액션은 요소 타입이 이벤트를 수신할 때 나타나야 하는 동작으로 볼 수 있습니다. 예를 들어, 체크박스는 클릭 이벤트에 대한 응답으로 상태를 토글해야 합니다. 이를 실행하기 위해 모든 체크박스에 콜백을 등록하는 대신 기본 액션 가상 함수를 오버라이드할 수 있습니다.

커스텀 컨트롤 베스트 프랙티스

다음은 커스텀 컨트롤에 대한 베스트 프랙티스입니다.

동작 구현

기본 액션으로 요소의 동작을 구현해야 합니다. 인스턴스에 부착된 콜백에서 PreventDefault()를 호출하여 기본 요소 동작을 취소할 수 있습니다.

동작을 기본 액션으로 구현하는 경우 추가적인 이점은 다음과 같습니다.

  • 기본 액션은 콜백 레지스트리 룩업을 필요로 하지 않습니다.
  • 콜백이 없는 인스턴스는 전파 프로세스에 들어가지 않습니다.

유연성 향상을 위해 이벤트 타겟의 기본 액션을 이벤트 디스패치 프로세스 동안 두 지점에서 실행할 수 있습니다.

  • 타겟 콜백이 실행된 직후, 트리클다운 및 버블업 전파 단계 사이에 ExecuteDefaultActionsAtTarget()을 오버라이드합니다.
  • 이벤트 디스패치 프로세스 끝에서 ExecuteDefaultActions()를 오버라이드합니다.

클래스 기본 동작

ExecuteDefaultActions()에서 클래스 기본 액션을 구현하십시오. 이렇게 하면 더 많은 클래스 오버라이드 옵션을 이용할 수 있습니다. 이벤트 전파 프로세스의 트리클다운 단계 또는 버블업 단계 동안 PreventDefault()를 호출하여 클래스를 오버라이드할 수 있습니다.

이벤트가 부모 요소로 전파되어서는 안 되는 경우, 기본 액션 실행 중 이벤트 전파를 중단해야 합니다. 예를 들어, 텍스트 필드가 콘텐츠를 삭제하는 Delete 키와 같이 필드 값을 변경하는 KeyDownEvent를 수신합니다. 이 이벤트는 부모 시각적 요소로 전파되어서는 안 됩니다. 이러한 기본 액션을 구현하려면 ExecuteDefaultActionsAtTarget()을 사용하고, StopPropagation()을 호출하여 버블업 단계에서 이벤트가 프로세싱되지 않게 하십시오.

기본 액션은 이벤트 타겟에 대해서만 실행됩니다. 클래스가 자신의 자식 또는 부모 요소를 타게팅하는 이벤트에 응답하려면 트리클다운 전파 단계 또는 버블업 전파 단계 중 이벤트를 수신하기 위한 콜백을 등록해야 합니다. 성능 향상을 위해 클래스에 콜백을 등록하지 마십시오.

이벤트 전파 중지 및 기본 액션 취소

콜백 또는 기본 액션 내에서 이벤트를 처리할 때 추가적인 이벤트 전파 및 기본 액션 실행을 중단할 수 있습니다. 예를 들어, 부모 패널은 자식이 이벤트를 수신하지 않도록 트리클다운 단계 중 전파를 중단할 수 있습니다.

이벤트 클래스 자체 내에서 EventBase.PreDispatch()EventBase.PostDispatch() 메서드의 실행을 방지할 수는 없습니다.

다음 메서드는 이벤트 전파와 기본 액션에 영향을 미칩니다.

  • StopImmediatePropagation():이벤트 전파 프로세스를 즉시 중단하므로 이벤트에 대해 다른 콜백이 실행되지 않습니다.그러나 ExecuteDefaultActionAtTarget()ExecuteDefaultAction() 기본 동작은 계속 실행됩니다.
  • StopPropagation():현재 요소의 마지막 콜백 후에 이벤트 전파 프로세스를 중단합니다.이렇게 하면 모든 콜백이 현재 요소에 대해 실행되지만, 더 이상 요소가 이벤트에 반응하지 않습니다.ExecuteDefaultActionAtTarget()ExecuteDefaultAction() 기본 동작은 계속 실행됩니다.
  • PreventDefaultAction():이벤트 전파 프로세스가 ExecuteDefaultActionAtTarget()ExecuteDefaultAction() 기본 동작을 호출하지 못하도록 합니다.PreventDefaultAction()은 다른 콜백의 실행을 막지 않으며 버블업 단계 동안 ExecuteDefaultActionAtTarget() 동작에 영향을 미치지 않습니다.

추가 리소스

이벤트 디스패치
이벤트 합성 및 전송