이벤트 시스템 (Event System)
•
관련 소스 파일
◦
GameFramework/Base/EventPool/EventPool.cs
◦
GameFramework/Entity/EntityManager.EntityGroup.cs
◦
GameFramework/Entity/EntityManager.EntityInfo.cs
◦
GameFramework/Entity/IEntityGroup.cs
◦
GameFramework/Entity/IEntityManager.cs
◦
GameFramework/UI/IUIGroup.cs
◦
GameFramework/UI/IUIManager.cs
◦
GameFramework/UI/UIManager.UIGroup.cs
이벤트 시스템은 타입-안전(type-safe)한 메시지 전달 프레임워크로, 서로 직접적인 의존성을 만들지 않고 컴포넌트 간 통신을 가능하게 한다.
퍼블리셔-서브스크라이버 패턴을 구현하여, 컴포넌트가 특정 이벤트 타입을 구독하고, 이벤트를 발행(fire)하며, 이벤트 발생 시 이를 처리할 수 있게 한다.
개요 (Overview)
이벤트 시스템은 이벤트를 처리하기 위한 중앙 메커니즘을 제공하며, 주요 특징은 다음과 같다:
•
스레드 안전(thread-safe)한 이벤트 발행과 지연 처리
•
즉시 이벤트 발행(동기 처리용)
•
이벤트 핸들러 등록 및 관리
•
특정 핸들러가 없을 때 기본 처리 제공
핵심 컴포넌트 (Core Components)
EventPool
EventPool<T> 은 이벤트 시스템의 중심 컴포넌트로, 이벤트 등록, 큐잉(queueing), 디스패칭(dispatching)을 관리한다.
EventPool<T>는 다음을 관리한다:
•
이벤트 ID로 인덱싱된 이벤트 핸들러의 멀티 딕셔너리
•
지연 처리를 위한 이벤트 큐
•
처리되지 않은 이벤트를 위한 기본 핸들러
EventPoolMode
Event Pool의 동작은 EventPoolMode 플래그로 제어된다:
모드 | 설명 |
Default | 기본 모드 (모든 핸들러 허용, 중복 금지, 핸들러 없음 시 예외 발생) |
AllowMultiHandler | 하나의 이벤트 타입에 대해 여러 이벤트 핸들러 허용 |
AllowDuplicateHandler | 동일한 핸들러를 여러 번 등록 가능 |
AllowNoHandler | 핸들러가 없을 때도 예외를 억제 |
이벤트 흐름 (Event Flow)
이벤트 등록 (Event Registration)
알림을 받으려면, 컴포넌트는 Event Pool에 핸들러를 등록해야 한다.
Subscribe 메서드를 사용하여 이벤트 ID와 델리게이트 핸들러를 전달해 구독할 수 있다.
이벤트 발행과 처리 (Event Firing and Processing)
이벤트 발행 방법은 두 가지이다:
1.
지연 발행(Fire): 스레드 안전하며, 다음 Update 주기에서 처리됨
2.
즉시 발행(FireNow): 즉시 처리되지만 스레드 안전하지 않음
Update 메서드 동안, 큐에 쌓인 모든 이벤트가 처리되고 등록된 핸들러로 디스패치된다.
이벤트 처리 (Event Handling)
이벤트가 처리될 때, 시스템은 해당 핸들러를 찾아 호출한다.
특정 핸들러가 없을 경우, 기본 핸들러와 설정 옵션에 따라 처리되지 않은 이벤트에 대한 대응이 가능하다.
프레임워크 컴포넌트와의 통합 (Integration with Framework Components)
이벤트 시스템은 GameFramework 전반에서 컴포넌트 간 통신에 사용된다. 대표적인 예는 다음과 같다:
Entity Manager 이벤트
엔티티 매니저는 엔티티 라이프사이클과 관련된 이벤트를 발생시킨다:
•
ShowEntitySuccess: 엔티티가 성공적으로 표시되었을 때
•
ShowEntityFailure: 엔티티 표시가 실패했을 때
•
ShowEntityUpdate: 엔티티 로딩 과정 중
•
ShowEntityDependencyAsset: 엔티티 의존 에셋 로딩 시
•
HideEntityComplete: 엔티티가 숨겨졌을 때
UI Manager 이벤트
UI 매니저는 UI 폼 동작을 이벤트로 전달한다:
•
OpenUIFormSuccess: UI 폼이 성공적으로 열렸을 때
•
OpenUIFormFailure: UI 폼 열기에 실패했을 때
•
OpenUIFormUpdate: UI 폼 로딩 과정 중
•
OpenUIFormDependencyAsset: UI 폼 의존 에셋 로딩 시
•
CloseUIFormComplete: UI 폼이 닫혔을 때
베스트 프랙티스 (Best Practices)
Fire vs FireNow 사용 시점
•
Fire: 스레드 안전한 이벤트 디스패치가 필요할 때 (특히 메인 스레드가 아닌 경우)
•
FireNow: 즉시 처리가 필요하고 이미 메인 스레드에서 실행 중일 때
이벤트 핸들러 관리
•
불필요한 핸들러는 반드시 해제(unsubscribe)하여 메모리 누수를 방지할 것
•
이벤트 풀 모드를 고려하여 설계할 것:
◦
AllowMultiHandler: 여러 수신자가 필요한 브로드캐스트 이벤트용
◦
AllowNoHandler: 핸들러가 없어도 되는 선택적 이벤트용
스레드 안전 고려 사항
•
Fire 는 스레드 안전하지만, 이벤트는 다음 update 주기에서 처리됨
•
FireNow 는 스레드 안전하지 않지만 즉시 처리됨
•
Event Pool의 Update 메서드는 반드시 메인 스레드에서 호출되어야 함
중요한 주의사항 (Important Notes)
•
Fire 로 큐잉된 이벤트는 즉시 처리되지 않고, 다음 Update 호출 시 처리된다
•
EventPool 는 제네릭으로, 이벤트 인자는 반드시 BaseEventArgs 를 상속해야 한다
•
이벤트 핸들러는 GC 부담을 줄이기 위해 레퍼런스 풀 시스템으로 관리된다