[Unity] Event

Lingtea_luv·2025년 4월 18일

Unity

목록 보기
7/30
post-thumbnail

UnityEvent


UnityEvent는 델리게이트와 비슷한 역할로 Unity에서 편하게 사용할 수 있도록 고안된 기능으로, 직렬화가 가능하여 인스펙터 창에서 다른 컴포넌트의 메서드를 등록하고 실행할 수 있게 한다.

이는 디자이너와 개발자 간의 협업을 더 쉽게 만들어주는 시스템으로써의 장점을 갖는다.

public class UnityEventTest : MonoBehaviour
{
	public UnityEvent myEvent;
  	
	private void Update()
	{
		if(Input.GetKeyDown(KeyCode.Space))
    	{
    		myEvent?.Invoke();  // 등록된 메서드(Test) 호출
   		}
	}
}

public class Tester : MonoBehaviour
{
	public void Test()
	{
		Debug.Log("인스펙터로 구독 가능");
	}
}

위와 같은 코드를 작성하면 인스펙터 창에서 myEventTesterTest()를 등록하여 간편하게 사용할 수 있다.

Method

Invoke()			// 구독 함수 실행
AddListener()		// 함수 구독
RemoveListener()	// 구독 취소
public class UnityEventTest : MonoBehaviour
{
	public UnityEvent myEvent;
 
 	public void Awake()
    {
    	// C# event와 달리 해당 문법은 지원하지 않는다.
    	// myEvent += Test1;  
        myEvent.AddListener(Test1);
        myEvent.RemoveListener(Test1);
    }
    
    private void Update()
	{
    	myEvent?.Invoke();
    }
    
    private void Test1(){}

Parameter

UnityEvent도 델리게이트와 마찬가지로 소스코드 내에서는 매개변수가 동일해야 AddListener로 구독하는 것이 가능하다.

public class UnityEventTest : MonoBehaviour
{
	public UnityEvent<int> myEvent;
    
    public void Awake()
    {
        myEvent.AddListener(Test1);  // 가능
        myEvent.AddListener(Test2);  // 불가능
    }
        
    public void Test1(int n) {}
    
    public void Test2() {}

하지만 인스펙터에서는 매개변수가 다른 함수도 이벤트에 등록할 수 있으며, 등록을 할 때 매개변수에 어떤 값을 넣을지 지정할 수 있다. 반대로 매개변수가 필요한 이벤트여도 매개변수가 없는 함수를 등록하여 사용하는 것도 가능하다.

이는 Unity 인스펙터에서 UnityEvent에 메서드를 연결할 때 C#의 Reflection을 사용하기 때문이다. Unity는 런타임에 메서드 정보를 조회하고 인스펙터에서 지정한 값으로 파라미터를 자동으로 넘겨줄 수 있어, 코드 상에서는 시그니처가 일치해야하지만 인스펙터에서는 더 유연하게 사용 가능하다.

public class UnityEventTest : MonoBehaviour
{
	public UnityEvent myEvent;
    public UnityEvent<float> myFloatEvent;
  	
	private void Update()
	{
		if(Input.GetKeyDown(KeyCode.Space))
    	{
    		myEvent?.Invoke();  	 	 // Test1 구독 및 실행 가능 
            myFloatEvent?.Invoke(1.5f);  // Test2 구독 및 실행 가능
   		}
	}
}

public class Tester : MonoBehaviour
{
	public void Test1(int n)
	{
		Debug.Log("인스펙터로 구독 가능");
	}
    
    public void Test2()
	{
		Debug.Log("인스펙터로 구독 가능");
	}
}

주의할 점

  1. 직렬화 기능을 가지고 있기에, MonoBehaviour를 상속 받은 클래스만 인스펙터에 노출된다.
  2. 1번과 마찬가지로 private도 노출되지 않으며, static 함수도 등록할 수 없다.
  3. 이벤트가 많아지면 관리가 불가능하며, 매개변수가 2개 이상인 함수는 인스펙터 상으로 등록할 수 없다.
  4. 인스펙터에서 추가하는 경우 소스코드에서 어디서 붙였는지 확인하는 것이 불가능하다.
  5. 등록된 메서드는 직렬화되어 저장되므로, 등록한 오브젝트나 컴포넌트가 삭제되면, null 참조 오류가 발생할 수 있다.

UnityAction

유니티 초창기 여러 언어를 지원할 때 일부 언어의 경우 델리게이트 문법이 존재하지않아 과거 UnityAction이라는 기능이 만들어졌다.

UnityEvent 또한 내부적으로는 UnityAction으로 구현되어있으나, C#에서의 Action과 동일한 기능을 가지고 있기에 현재는 대부분의 경우 Action을 사용하거나 UnityEvent를 직접 사용하는 편이다.

public class UnityActionTest : MonoBehaviour
{
	public event UnityAction OnDied;
    public event Action myDel;
}
profile
뚠뚠뚠뚠

0개의 댓글