[ C#/Unity ] event, UnityEvent

Lutica_·2025년 3월 29일

Event Driven Programming

  • JS, C#(UI중심 엔진- unity등)과 같은 언어들은 Event Loop를 기반으로 하는 Event Driven Programming을 지원하는 경우가 많다.
  • 실행시킬 함수의 포인터만 등록시킴으로서 결합도를 최소화 시킬 수 있는 방안으로 알려져 있다.

Pub-Sub Pattern

  • Event Driven ProgrammingPub-Sub Pattern과 유사하게 실현된다.
  • 어떤 Class에 어떤 method를 실행시킬 것인지를 등록, 삭제하는 것을 의미한다.

C# keyword event

https://learn.microsoft.com/ko-kr/dotnet/csharp/language-reference/keywords/event

  • 기본적인 C# / .Net의 스크립팅에서는 인스턴스와 인자들을 받아서 이벤트의 등록이 가능하다.
  • +=, -=가 기본적으로 override 되어있고, 사용방법은 직관적으로 구독, 취소 할 수 있다.
public class SampleEventArgs
{
    public SampleEventArgs(string text) { Text = text; }
    public string Text { get; } // readonly
}

public class Publisher
{
    // Declare the delegate (if using non-generic pattern).
    public delegate void SampleEventHandler(object sender, SampleEventArgs e);

    // Declare the event.
    public event SampleEventHandler SampleEvent;

    // Wrap the event in a protected virtual method
    // to enable derived classes to raise the event.
    protected virtual void RaiseSampleEvent()
    {
        // Raise the event in a thread-safe manner using the ?. operator.
        SampleEvent?.Invoke(this, new SampleEventArgs("Hello"));
    }
}

Unity UnityEvent

class in UnityEngine.Events

https://docs.unity3d.com/6000.0/Documentation/ScriptReference/Events.UnityEvent.html

  • 이 키워드는 Class로 취급된다.

  • 과거의 공식적인 설명에 근거한다면, UnityEvent는 추가 프로그래밍 및 스크립트 설정 없이도 사용자 기반 콜백이 편집 시간부터 런타임까지 유지되도록 하는 방법이라고 설명한다.

  • 이 말은 플레이모드에 진입해도 중간중간 컴파일이 다시되어도 문제없이 다시 실행된다는 것이다.

    이는 Inspector에서 삭제되지 않음을 의미한다.
    "추가 프로그래밍 없이": 코드를 수정하지 않고 Inspector(에디터) 상에서 드래그 앤 드롭으로 이벤트를 연결할 수 있다는 뜻이다. (협업에 유리)
    "편집 시간부터 런타임까지 유지": 연결 정보를 직렬화(Serialization)해서 저장한다는 의미다.

  • 사용법은 살짝 다르다. AddListenerRemoveListener로 이벤트를 추가/제거해야 한다.

  • 호출은 Invoke로 가능하다. Generic을 사용하면 인자도 넣을 수 있다.

  • Trade-off가 좀 있다.

    편리한 만큼 순수 C# event에 비해 성능 오버헤드가 있고, 호출 시 가비지(Garbage)가 발생할 수 있다.
    따라서 매 프레임 호출되는 Update 문보다는, UI 클릭이나 게임 로직의 상태 변화 등 빈도가 적은 이벤트에 사용하는 것이 적합하다.

  • 예시코드는 아래와 같다.

using UnityEngine;
using UnityEngine.Events;

public class ExampleClass : MonoBehaviour
{
    UnityEvent m_MyEvent;

    void Start()
    {
        if (m_MyEvent == null)
            m_MyEvent = new UnityEvent();

        m_MyEvent.AddListener(DoSomething);
    }
    
    void OnDestroy()
    {
    	m_MyEvent.RemoveListener(DoSomething);
    }
    void Update()
    {
        if (Input.anyKeyDown && m_MyEvent != null)
        {
            m_MyEvent.Invoke(); 
        }
    }

    void DoSomething()
    {
        Debug.Log("Callback called");
    }
}

profile
해보고 싶고, 하고 싶은 걸 하는 사람

0개의 댓글