[C#/Unity] 이벤트
댓글 0
댓글을 작성하려면 로그인이 필요합니다.
아직 댓글이 없습니다. 첫 번째 댓글을 작성해보세요!
게임을 개발하다 보면 "적이 죽었을 때 점수를 올리고, 사운드를 재생하고, UI를 갱신해야 한다"는 상황이 자주 생긴다. 이때 모든 처리를 한 곳에 몰아넣으면 코드는 금방 엉망이 되고, 코드 간 의존성이 커지게 된다.
이런 문제를 해결해주는 것이 이벤트다
이벤트는 "어떤 일이 일어났을 때 관심 있는 쪽에서 알아서 반응하게 만드는 구조"다. 직접 함수를 호출하는 대신, 신호만 쏘면 등록된 쪽에서 각자 처리한다. 덕분에 코드 간의 의존성이 줄어들고, 기능을 추가하거나 수정할 때 훨씬 편해진다.
주요 용어
이벤트는 delegate에 event 키워드를 추가한 것이다
주의사항
null 조건 연산자
이벤트에 구독자가 없으면 null이므로 호출 시 예외가 발생할 수 있음
class Button
{
public event EventHandler Click;
public void OnClick()
{
// null 체크 후 호출 (기존 방식)
if (Click != null)
{
Click();
}
// null 조건 연산자 사용 (권장)
Click?.Invoke();
}
}
null 체크하면서 이벤트를 호출하는 것 보다 ?. null 조건 연산자를 사용하여 코드를 간결하게 작성할 수 있다
이벤트 구독과 해제
구독을 해제하지 않으면 메모리 누수가 발생할 수 있다
유니티에서 이벤트를 호출하는 방법이 여러가지가 있지만 인스펙터에서 이벤트를 노출하는 방법인 UnityEvent를 연습
기본 UnityEvent (매개변수 없음)
public class Player : MonoBehaviour
{
public int hp = 100;
// 인스펙터에서 보이게 하려면 public 또는 [SerializeField]
public UnityEvent OnDead;
public void TakeDamage(int damage)
{
hp -= damage;
if (hp <= 0)
{
OnDead?.Invoke();
}
}
}

인스펙터에 이벤트가 생성된걸 볼 수 있다.

+버튼을 눌러 객체(이벤트 호출 시 실행될 함수가 있는 객체)를 넣어서 함수를 설정해주면 이벤트 구독이 된다.
매개변수 있는 UnityEvent
public class OnHpChangedEvent : UnityEvent<int> { }
public class Player : MonoBehaviour
{
public int hp = 100;
public OnHpChangedEvent OnHpChanged;
public UnityEvent OnDead;
public void TakeDamage(int damage)
{
hp -= damage;
OnHpChanged?.Invoke(hp); // 현재 HP를 넘김
if (hp <= 0)
{
OnDead?.Invoke();
}
}
}
구독하는 쪽
public class UIManager : MonoBehaviour
{
[SerializeField] private Player player;
private void OnEnable()
{
player.OnHpChanged.AddListener(UpdateHpBar);
player.OnDead.AddListener(ShowGameOver);
}
private void OnDisable()
{
player.OnHpChanged.RemoveListener(UpdateHpBar);
player.OnDead.RemoveListener(ShowGameOver);
}
private void UpdateHpBar(int currentHp)
{
Debug.Log($"HP 바 갱신: {currentHp}");
}
private void ShowGameOver()
{
Debug.Log("게임 오버 UI 표시");
}
}
매개변수가 있는 이벤트는 같은 데이터형을 매개변수로 받는 함수를 구독하도록 해줘야한다.