본문 바로가기
C#

event Action 을 활용한 이벤트 처리

by Oz Driver 2025. 3. 11.

게임을 만들다 보면 특정 상황에서 여러 객체가 동시에 반응해야 할 때가 많습니다. 예를 들어, 플레이어가 사망하면 게임 오버 화면이 표시되고, 점수가 저장되며, 배경음악이 멈추는 상황이 있을 수 있습니다. 이를 효율적으로 관리하기 위해 event와 Action을 활용한 이벤트 시스템을 사용할 수 있습니다.

 

 

event Action의 개념

어떤 마을에서 "불이야!" 라고 외쳤다고 가정해봅시다.

이 소리를 들으면 각자의 역할을 가진 사람들이 자동으로 반응합니다.

 

소방관은 불을 끄러 출동하고 ... 

이웃들은 대피하며 ...

방송국은 긴급 속보를 내보냅니다. 

 

즉, 불이 난 사람이 일일이 지시하지 않아도 "불이야!" 라는 신호만 전달하면 관련된 사람들이 각자 반응하는 구조입니다.

게임에서도 동일한 개념을 적용할 수 있습니다. 게임 오버라는 이벤트가 발생하면, 미리 등록된 여러 개의 동작이 자동으로 실행되는 방식입니다. 이를 C#에서는 event Action을 이용해 구현할 수 있습니다.

 

 

event Action을 활용한 이벤트 처리 예제

1. GameManager에서 onGameOver 이벤트 정의

using System;
using UnityEngine;

public class GameManager : MonoBehaviour
{
    public static GameManager instance;
    public event Action onGameOver;

    private void Awake()
    {
        instance = this;
    }

    public void GameOver()
    {
        Debug.Log("게임 오버!");
        onGameOver?.Invoke(); // 모든 이벤트 리스너 실행
    }
}

 

GameManager는 GameOver() 를 통해 onGameOver 이벤트에 등록된 모든 동작이 한꺼번에 실행됩니다.

만약 등록된 함수들이 없을 경우 null 이 되기 때문에 ?. 를 써서 Invoke() 에 접근하지 않도록 예외 처리가 되었습니다.

 

2. Bird 클래스에서 이벤트 구독 및 반응

public class Bird : MonoBehaviour
{
    private Rigidbody2D rb;

    private void Start()
    {
        GameManager.instance.onGameOver += StopBird;
        rb = GetComponent<Rigidbody2D>();
    }

    private void OnCollisionEnter2D(Collision2D collision)
    {
        GameManager.instance.GameOver(); // 게임 오버 신호 발생
    }

    void StopBird()
    {
        rb.velocity = Vector2.zero;
        rb.isKinematic = true;
        Debug.Log("새 멈춤!");
    }
}

 

이제 새가 장애물과 충돌하면 GameManager.instance.GameOver() 가 실행되면서 onGameOver 이벤트가 발생합니다. 이 이벤트를 듣고 Bird는 자신이 해야 할 동작(새 멈추기)을 수행합니다.

GameManager.instance.onGameOver += StopBird;

이렇게 이벤트를 등록했기 때문입니다. 

 

3. UIManager에서 UI 표시

public class UIManager : MonoBehaviour
{
    private void Start()
    {
        GameManager.instance.onGameOver += ShowGameOverUI;
    }

    void ShowGameOverUI()
    {
        Debug.Log("게임 오버 UI 표시!");
    }
}

 

마찬가지로 UIManager 에서는 게임 오버가 발생하면 어떻게 처리를 할지 함수를 구현하고 그 함수를 onGameOver 에 += (등록) 해두었습니다. 

 

4. AudioManager에서 사운드 재생

public class AudioManager : MonoBehaviour
{
    private void Start()
    {
        GameManager.instance.onGameOver += PlayGameOverSound;
    }

    void PlayGameOverSound()
    {
        Debug.Log("게임 오버 사운드 재생!");
    }
}

 

여기서도 마찬가지 입니다. 게임 오버 신호를 듣고 배경음악이 멈추거나 효과음이 재생될 수 있습니다.

 

 

5. 이벤트 처리 흐름

먼저, Bird가 장애물과 충돌하면 GameManager.instance.GameOver(); 가 호출됩니다.

그 다음, GameOver()가 onGameOver?.Invoke(); 실행하여 등록된 모든 함수를 실행합니다.

그리고 나면, Bird, UIManager, AudioManager 등 각자 등록한 동작을 수행합니다.

 

이 과정은 불이 났을 때 마을 사람들이 각자 역할에 맞게 행동하는 방식과 동일합니다.

 

 

왜 event Action을 사용해야 할까?

유지보수가 쉬움

GameManager는 게임 오버라는 이벤트를 발생시킬 뿐 실제로 어떤 일이 일어날지는 신경 쓰지 않습니다.

새로운 동작을 추가할 때 +=로 쉽게 추가할 수 있습니다.

확장성이 높음

나중에 "게임 오버 시 광고를 띄우는 기능"을 추가하고 싶다면?

GameManager.instance.onGameOver += ShowAd; 만 추가하면 됩니다.

객체 간 결합도 낮음

GameManager가 직접 UIManager나 AudioManager를 호출하는 것이 아니라,

이벤트를 통해 각자가 스스로 반응하도록 유도하므로 코드가 더 유연해집니다.

 

 

결론

event Action을 사용하면 하나의 이벤트가 발생할 때 여러 동작을 한꺼번에 실행할 수 있습니다.

GameManager는 이벤트를 전달하는 역할만 하며, 각 객체는 알아서 반응합니다.

 

이 방식은 유지보수와 확장성이 뛰어나며, 객체 간 결합도를 낮춰 더 나은 설계를 가능하게 합니다.

결국, 이벤트 기반 프로그래밍을 활용하면 코드가 더 유연하고 관리하기 쉬워집니다.