728x90
반응형
Unity에서 게임을 개발하다 보면 여러 오브젝트가 서로 상호작용할 일이 많습니다.
예를 들어:
- 플레이어가 공격하면 UI 체력이 줄어야 하고
- 적이 피해를 받고 사망하면 점수 시스템이 반응해야 하고
- 사운드 매니저가 효과음을 재생해야 하는 경우
이때 직접 참조(player.OnAttack += ui.UpdateHealth)로 연결하면,오브젝트가 많아질수록 코드가 뒤엉키고 유지보수가 어려워집니다.
여기서 이벤트버스(Event Bus) 패턴이 유용합니다.
1️⃣ 이벤트버스(Event Bus)란?
Event Bus는 이벤트를 “중앙 허브”로 모아 관리하고, 필요할 때 전달하는 패턴입니다.
즉,
- 이벤트를 발행(Publish) 하는 오브젝트
- 이벤트를 구독(Subscribe) 하는 오브젝트
이 둘을 직접 연결하지 않고,중앙의 Event Bus를 통해 통신하게 하는 방식입니다.
장점:
- 오브젝트 간 결합도(Coupling) 최소화
- 이벤트 추가/삭제가 쉽고, 유지보수가 간단
- 여러 시스템에서 동일 이벤트를 동시에 처리 가능
2️⃣ 간단한 이벤트버스 구현 예제
🔹 EventBus 클래스
using System;
using System.Collections.Generic;
public static class EventBus
{
// 타입별 이벤트 저장
private static Dictionary<Type, Action<object>> _eventTable = new Dictionary<Type, Action<object>>();
// 이벤트 구독
public static void Subscribe<T>(Action<T> listener)
{
Type type = typeof(T);
if (_eventTable.ContainsKey(type))
{
_eventTable[type] += (obj) => listener((T)obj);
}
else
{
_eventTable[type] = (obj) => listener((T)obj);
}
}
// 이벤트 구독 해제
public static void Unsubscribe<T>(Action<T> listener)
{
Type type = typeof(T);
if (_eventTable.ContainsKey(type))
{
_eventTable[type] -= (obj) => listener((T)obj);
}
}
// 이벤트 발행
public static void Publish<T>(T eventData)
{
Type type = typeof(T);
if (_eventTable.ContainsKey(type))
{
_eventTable[type]?.Invoke(eventData);
}
}
}
💡 포인트:
T 타입별로 이벤트를 구분해서 발행하고, 구독자가 타입별로 받을 수 있도록 구현했습니다.
🔹 이벤트 데이터 정의
public class PlayerDamageEvent
{
public int Damage;
public PlayerDamageEvent(int damage)
{
Damage = damage;
}
}
public class EnemyDeadEvent
{
public int Score;
public EnemyDeadEvent(int score)
{
Score = score;
}
}
🔹 이벤트 발행 예제 (Publisher)
using UnityEngine;
public class Player : MonoBehaviour
{
public void TakeDamage(int damage)
{
Debug.Log($"플레이어가 {damage} 데미지 받음");
EventBus.Publish(new PlayerDamageEvent(damage));
}
}
🔹 이벤트 구독 예제 (Subscriber)
using UnityEngine;
public class UIManager : MonoBehaviour
{
private void OnEnable()
{
EventBus.Subscribe<PlayerDamageEvent>(OnPlayerDamage);
}
private void OnDisable()
{
EventBus.Unsubscribe<PlayerDamageEvent>(OnPlayerDamage);
}
private void OnPlayerDamage(PlayerDamageEvent e)
{
Debug.Log($"UI 업데이트: 플레이어 체력 감소 {e.Damage}");
}
}
3️⃣ 이벤트버스 패턴 사용 시 주의점
- 메모리 관리
- 구독 후 반드시 해제(Unsubscribe) 필요
- 안 하면 씬 전환 시 메모리 누수 발생 가능
- 디버깅 어려움
- 이벤트가 어디서 호출되는지 추적하기 어려움
- 로그를 적극 활용하거나 이벤트 이름/타입을 명확히 작성
- 고빈도 이벤트 주의
- 프레임마다 호출되는 이벤트에는 적합하지 않음
- Update 내에서 매번 Publish 하는 것은 피해야 함
4️⃣ 이벤트버스를 활용한 장점
느슨한 결합 | Publisher와 Subscriber가 서로 몰라도 됨 |
재사용성 | 같은 이벤트를 여러 시스템에서 동시에 처리 가능 |
확장 용이 | 새 Subscriber만 추가하면 기능 확장 가능 |
5️⃣ 실제 게임에서의 활용 예시
- 플레이어 공격 → 적 체력 감소 + UI 체력 감소 + 사운드 재생
- 적 사망 → 점수 증가 + 아이템 드롭 + 사운드 재생
- 게임 종료 → UI, 점수판, 효과음 등 여러 시스템 동시에 반응
🔑 핵심: 중앙 이벤트 버스를 통해 각 시스템을 독립적으로 연결
6️⃣ 마무리
Unity에서 이벤트버스 패턴을 사용하면:
- 복잡한 오브젝트 간 상호작용을 간단히 관리
- 유지보수성 높은 코드 구조를 만들 수 있습니다.
특히 큰 프로젝트나 여러 시스템이 얽힌 게임에서
상태 관리와 UI, 사운드, 점수 시스템 같은 다중 이벤트 처리가 필요할 때
이벤트버스 패턴은 매우 강력한 도구가 됩니다. 🎯
728x90
반응형
'개발 > Unity' 카테고리의 다른 글
Unity 내장 오브젝트 풀(Object Pool) 사용하기 (0) | 2025.10.13 |
---|---|
Unity에서 tag 비교할 때 CompareTag()를 사용해야 하는 이유 (0) | 2025.10.12 |
Unity에서 커맨드(Command) 패턴 활용하기 (0) | 2025.10.11 |
Unity에서 상태패턴으로 캐릭터 움직임과 공격 구현하기 (0) | 2025.10.07 |
Unity에서 추상 클래스 기반 Singleton 패턴 구현하기 (0) | 2025.10.06 |