Delegate, Action, Event

1. 델리게이트란?

델리게이트는 함수 포인터 역할을 수행하는 C#의 참조 타입이다.

다른 함수를 참조할 수 있는 변수처럼 사용되며, 함수를 대신해서 작동하게 한다.

 

 

1.1. 델리게이트의 사용

  - 함수의 이름과 매개 변수를 지정하여 객체를 생성

  - 한 함수에서 다른 함수로 동적 변경이 가능

  - 입력 파라미터에 따라 결과가 출력되며, 로그를 통해 출력값을 확인 가능

 

ex)

간단한 계산함수

public class DelegateExample : MonoBehaviour
{
    // 델리게이트 선언
    private delegate int CalculateDelegate(int a, int b);
    private CalculateDelegate calculateOperation;

    // 할당할 함수
    private int Add(int a, int b) => a + b;
    private int Multiply(int a, int b) => a * b;
    
    void Start()
    {
        // 델리게이트에 함수 할당
        calculateOperation = Add;
        Debug.Log($"덧셈 결과: {calculateOperation(5, 3)}");

        // 다른 함수로 변경
        calculateOperation = Multiply;
        Debug.Log($"곱셈 결과: {calculateOperation(5, 3)}");
    }
}

 

 

2. 액션(Action)이란?

입력과 출력이 없는 메서드를 가리키는 델리게이트의 간소화된 형태이다.

매개변수를 void로 설정 가능하며, 다양한 호출 결과를 다룰 수 있다.

etc-image-0

 

2.1. 액션의 사용

  - += 연산자를 사용하여 메서드를 등록

  - 등록된 메서드는 원하는 시점에 반복 실행 가능

  - 매개변수가 없는 경우 꺽쇠 괄호를 생략
  - 여러 함수를 연달아 호출 가능

 

ex)

게임 시작/일시정지 이벤트, 점수시스템 연동

public class GameManager : MonoBehaviour
{
    // 게임 상태 변경 이벤트
    public static Action onGameStart;
    public static Action<int> onScoreChanged;  // 매개변수가 있는 Action

    private int currentScore = 0;

    void Start()
    {
        // 이벤트 리스너 등록
        onGameStart += StartGame;
        onScoreChanged += UpdateScoreUI;
    }

    void OnDestroy()
    {
        // 이벤트 리스너 제거
        onGameStart -= StartGame;
        onScoreChanged -= UpdateScoreUI;
    }

    public void StartGameButton()
    {
        // 이벤트 발생
        onGameStart?.Invoke();
    }

    public void AddScore(int points)
    {
        currentScore += points;
        onScoreChanged?.Invoke(currentScore);
    }

    private void StartGame()
    {
        // 게임 시작 로직
    }

    private void UpdateScoreUI(int newScore)
    {
        Debug.Log($"점수 : {newScore}점");
    }
}

 

 

3. 이벤트(Event) 시스템

event 키워드를 사용하여 델리게이트를 선언한다.

클래스 외부에서의 델리게이트 선언을 제한한다.

 

 

3.1. 이벤트의 사용

  - 연쇄 동작을 이끌어내는 트리거 역할

  - 이벤트 발생 시 구독 중인 처리들이 연쇄적으로 실행

  - 이벤트와 이벤트 리스너로 오브젝트 구분

 

ex)

UI시스템 연동, 메시지 표시 시스템, 인벤토리 UI 토글

public class UIManager : MonoBehaviour
{
    // event 키워드를 사용하여 선언
    private event Action<string> OnMessageReceived;
    public event Action<bool> OnInventoryStateChanged;

    // 이벤트 발생을 위한 메서드
    private void RaiseMessageEvent(string message)
    {
        OnMessageReceived?.Invoke(message);
    }

    void Start()
    {
        OnMessageReceived += DisplayMessage;
        OnInventoryStateChanged += ShowHideInventory;
    }

    public void ButtonClickHandler()
    {
        RaiseMessageEvent("버튼이 클릭되었습니다!");
    }

    public void InventoryButtonHandler(bool show)
    {
        OnInventoryStateChanged?.Invoke(show);
    }

    private void DisplayMessage(string message)
    {
        Debug.Log($"메시지 표시: {message}");
    }

    private void ShowHideInventory(bool show)
    {
        Debug.Log(show ? "인벤토리 열기" : "인벤토리 닫기");
    }

    void OnDestroy()
    {
        OnMessageReceived -= DisplayMessage;
        OnInventoryStateChanged -= ShowHideInventory;
    }
}

// event 사용 예시
public class GameController : MonoBehaviour
{
    [SerializeField]
    private UIManager uiManager;

    void Start()
    {
        // event는 클래스 외부에서 구독만 가능
        uiManager.OnInventoryStateChanged += HandleInventoryState;
        
        // 아래 코드는 컴파일 에러 발생 - event는 외부에서 직접 호출 불가
        uiManager.OnInventoryStateChanged.Invoke(true);
    }

    private void HandleInventoryState(bool isOpen)
    {
        Debug.Log($"인벤토리 상태 변경 감지: {isOpen}");
    }

    void OnDestroy()
    {
        if (uiManager != null)
        {
            uiManager.OnInventoryStateChanged -= HandleInventoryState;
        }
    }
}

 

 

4. 비교

Delegate

  - 가장 기본적인 형태로 event와 Action의 기반

  - 외부에서 직접 호출, 할당 가능

 

 

Action

  - .NET에서 미리 정의된 delegate 타입

  - 반환값이 없는 void 타입의 메서드만 참조 가능

  - delegate를 직접 선언할 필요 없이 바로 사용가능

 

 

Event

  - delegate 기반으로 캡슐화를 통해 안전한 이벤트 처리

  - 외부에서는 구독/구독취소만 가능

 

 

특징 Delegate Action Event
선언 필요 O X O
외부 직접 호출 O O X
외부 직접 할당 O O X
캡슐화 X X O
용도 메서드 참조 타입 정의 안전한 이벤트 처리 간단한 콜백 처리

 

'Unity' 카테고리의 다른 글

벡터  (0) 2024.11.01
Null 관련 연산자  (3) 2024.10.31
비동기 프로그래밍  (0) 2024.09.08
Rigidbody.velocity 천천히 떨어지는 문제  (0) 2024.04.21