Unity & C#/Scripting

Delegate, Event (2) - UnityEvent

coucou3 2020. 7. 9. 00:58
반응형

UnityEvent

 

UnityEvent는 C# Delegate를 Unity에서 쓰기 좋게 랩핑해 놓은 기능이다.

MonoBehaviour를 상속받는 모든 클래스에서 사용할 수 있고, UnityEvent 변수를 선언하면 인스펙터에 표시되고 영구적 콜백을 추가할 수 있다.

- 영구적 콜백은 인스펙터에서 등록해준 콜백으로, 런타임에서는 수정(등록/제거)할 수 없다.

 

 

선언

# UnityEventTest.cs 

using UnityEngine;
using UnityEngine.Events;	// UnityEvent 사용을 위해 import

public class UnityEventTest : MonoBehaviour
{
    public UnityEvent unityEvent;
}

 

public UnityEvent variable

 

 

등록/삭제

스크립트 상에서도 UnityEvent에 콜백을 등록할 수 있다.

이때 등록한 콜백은 비영구적 콜백으로 런타임 중에 수정이 가능하다.

using UnityEngine;
using UnityEngine.Events;

public class UnityEventTest : MonoBehaviour
{
    public UnityEvent unityEvent;
    
    
    void Start()
    {
        // Callback 등록
        unityEvent.AddListener(TestCallback);
    }


    private void TestCallback()
    {
        Debug.Log("TestCallback");
    }


    private void OnDestroy()
    {
        // Callback 제거
        unityEvent.RemoveListener(TestCallback);
    }
}

 

UnityEvent.AddListener는 UnityAction을 인자로 받는다.

UnityAction은 Unity 엔진에서 구현된 C# Delegate이다.

public void AddListener(Events.UnityAction call);

 

 

다중 등록/제거

한 개의 UnityEvent에 여러 개의 리스너를 등록할 수 있다.

UnityEvent.RemoveListener(UnityAction listener)로 특정 리스너를 지워줄 수도 있지만, RemoveAllListeners를 써서 모든 리스너를 지울 수 있다.

UnityEvent는 최대 4개의 인자를 갖는 UnityAction을 사용할 수 있다.

 

다만, Generic 형식의 UnityEvent는 추상클래스로써 사용하려면 클래스를 재정의해야 한다.

using System;
using UnityEngine;
using UnityEngine.Events;


// UnityEvent<T0, T1>을 상속받는 클래스 정의
[Serializable]
public class UnityEvent2 : UnityEvent<int, string>
{
}


public class UnityEventTest : MonoBehaviour
{
    // UnityEvent2 variable
    public UnityEvent2 unityEvent2;
    
    void Start()
    {
        unityEvent2 = new UnityEvent2();

        // 리스너 등록
        unityEvent2.AddListener(TestCallback2);
        unityEvent2.AddListener(TestCallback3);
    }


    private void TestCallback2(int num, string message)
    {
        Debug.Log($"TestCallback2 : int {num}, message {message}");
    }
    
    private void TestCallback3(int num, string message)
    {
        Debug.Log($"TestCallback3 : int {num}, message {message}");
    }


    private void OnDestroy()
    {
        // 모든 리스너 제거
        unityEvent2.RemoveAllListeners();
    }
}

 

 

호출

UnityEvent.Invoke()로 등록된 모든 리스너를 호출한다.

...

public class UnityEventTest : MonoBehaviour
{
    public UnityEvent<int, string> unityEvent2;
    
    
    void Start()
    {
        // 리스너 등록
        unityEvent2.AddListener(TestCallback2);
        unityEvent2.AddListener(TestCallback3);
        
        // 리스너 호출
        unityEvent2.Invoke();
    }
    
    ...
}

 

 

 

람다식 표현(Lambda Expression)

람다식을 사용하여 무명 메서드를 UnityEvent에 더 간단히 등록할 수 있다.

void Start
{
    // UnityEvent
    unityEvent.AddListener(() => Debug.Log("UnityEvent 1"));
    
    // UnityEvent<int, string>
    unityEvent2.AddListener(((num, message) =>
    Debug.Log($"UnityEvent<int, string> 1 : num {num}, message {message}")));
    
    unityEvent2.AddListener(((num, message) =>
    Debug.Log($"UnityEvent<int, string> 2 : num {num}, message {message}")));
        
    unityEvent.Invoke();
    unityEvent2.Invoke(1, "hello world");
}

 

 

 

 

참고

1) docs.unity3d.com/ScriptReference/Events.UnityEvent.html

2) rapapa.net/?p=2936

반응형

'Unity & C# > Scripting' 카테고리의 다른 글

Data based structure - ScriptableObject  (0) 2020.11.06
C# Extension Method(확장 메서드)  (0) 2020.08.14
Delegate, Event (1) - C# Delegate  (0) 2020.07.08