PART 2 · 강의 2/3

Event Dispatcher

옵저버 패턴 기반의 이벤트 디스패처로 블루프린트 간 느슨한 결합을 구현합니다

01

이벤트 디스패처란

옵저버 패턴과 이벤트 디스패처의 핵심 개념

이벤트 디스패처(Event Dispatcher)는 하나의 블루프린트에서 이벤트를 발생(Broadcast)시키면, 해당 이벤트에 구독(Bind)한 다른 블루프린트들이 알림을 받는 구조입니다. 이는 소프트웨어 디자인 패턴 중 옵저버 패턴(Observer Pattern)의 구현입니다.

Publisher
이벤트 소유자
Call / Broadcast
이벤트 발생
Subscriber A
Bind된 함수 실행
 
Subscriber B
Bind된 함수 실행

왜 이벤트 디스패처를 사용하는가?

느슨한 결합

Publisher는 누가 구독하는지 알 필요가 없습니다. 새 구독자를 추가해도 Publisher 코드를 수정할 필요가 없습니다.

1:N 통신

하나의 이벤트에 여러 구독자가 바인딩 가능합니다. 체력 변경 시 HUD, 사운드, VFX가 동시에 반응할 수 있습니다.

모듈화

각 시스템이 독립적으로 동작하면서 필요할 때만 통신합니다. 유지보수와 확장이 쉬워집니다.

02

디스패처 생성과 호출

이벤트 디스패처의 생성, 시그니처 정의, 호출 방법

생성 방법

My Blueprint 패널에서 Event Dispatchers 옆의 + 버튼을 클릭합니다.

Step 1: Create Event Dispatcher // BP_Player에 이벤트 디스패처 생성 BP_Player └─ Event Dispatchers └─ OnHealthChanged ├─ Input: NewHealth (Float) ├─ Input: MaxHealth (Float) └─ Input: DamageCauser (Actor Reference) // Details 패널 > Inputs 에서 파라미터 추가

호출(Call / Broadcast)

디스패처를 이벤트 그래프에 드래그하면 3가지 옵션이 표시됩니다:

옵션 설명
Call 이벤트를 발생시킵니다. 바인딩된 모든 함수/이벤트가 실행됩니다.
Bind 이벤트에 함수/이벤트를 구독합니다.
Unbind 구독을 해제합니다.
Unbind All 모든 구독을 해제합니다.
Event 바인딩용 이벤트 노드를 생성합니다 (자기 자신 블루프린트 내에서 사용).
Assign Bind + Event를 한 번에 생성합니다.
Step 2: Call the Dispatcher // BP_Player 내부 - 데미지를 받았을 때 디스패처 호출 [Event AnyDamage] ├─ Damage: Float └─ DamageCauser: Actor │ ├──> [Set Health] (Health - Damage) │ └──> [Call OnHealthChanged] ├─ NewHealth: Health ├─ MaxHealth: MaxHealth └─ DamageCauser: DamageCauser
03

바인딩 패턴

외부 블루프린트에서 이벤트 디스패처에 구독하기

외부 블루프린트에서 바인딩

다른 블루프린트(예: HUD, 적 AI)에서 BP_Player의 이벤트 디스패처에 바인딩하려면 먼저 BP_Player의 참조를 얻어야 합니다.

Bind from WBP_HealthBar (Widget Blueprint) // WBP_HealthBar에서 BP_Player의 OnHealthChanged에 바인딩 [Event Construct] │ ├──> [Get Owning Player Pawn] ──> [Cast To BP_Player] │ │ │ └─ As BP Player ──> [Bind Event to OnHealthChanged] │ └─ Event: [Custom Event: UpdateHealthBar] │ └──> (기타 초기화) // Custom Event: UpdateHealthBar [UpdateHealthBar] ├─ NewHealth (Float) ├─ MaxHealth (Float) └─ DamageCauser (Actor) │ └──> [Set Percent] (ProgressBar) └─ Percent: NewHealth / MaxHealth

Assign 단축키

Actor 참조에서 드래그하여 Assign OnHealthChanged를 선택하면, Bind 노드와 Custom Event가 한 번에 생성됩니다. 가장 빠른 바인딩 방법입니다.

Unbind (구독 해제)

Unbind Pattern // 위젯이 제거될 때 바인딩 해제 [Event Destruct] ──> [Unbind Event from OnHealthChanged] // 또는 모든 바인딩 한번에 해제 [Event Destruct] ──> [Unbind All Events from OnHealthChanged]
메모리 누수 방지

바인딩한 오브젝트가 파괴될 때 반드시 Unbind하세요. 그렇지 않으면 가비지 컬렉터가 해당 오브젝트를 회수하지 못하는 순환 참조가 발생할 수 있습니다. 특히 위젯과 Actor 간의 바인딩에서 흔히 발생합니다. Event Destruct(위젯) 또는 Event EndPlay(Actor)에서 Unbind를 수행하세요.

04

실전 활용 예제

게임에서 자주 사용되는 이벤트 디스패처 패턴

패턴 1: 사망 이벤트 체인

Death Event Chain // BP_Character에 OnDeath 디스패처 정의 OnDeath (DeadActor: Actor, Killer: Actor) // 구독자들: BP_GameMode ──Bind──> OnPlayerDeath() → 리스폰 타이머 시작 WBP_DeathScreen──Bind──> ShowDeathUI() → 사망 화면 표시 BP_MusicManager──Bind──> PlayDeathMusic() → BGM 변경 BP_DropSystem ──Bind──> SpawnDrops() → 아이템 드롭

패턴 2: 인벤토리 변경 알림

Inventory Update Pattern // BP_InventoryComponent에 정의 OnInventoryUpdated (SlotIndex: Integer, NewItem: S_ItemData, OldItem: S_ItemData) // BP_InventoryComponent 내부: [AddItem] ──> (배열에 추가) ──> [Call OnInventoryUpdated] [RemoveItem] ──> (배열에서 제거) ──> [Call OnInventoryUpdated] // WBP_Inventory(UI)에서 바인딩: [Bind Event to OnInventoryUpdated] ──> [Refresh Slot UI]

패턴 3: 퀘스트 진행 상황

Quest Progress Pattern // BP_QuestManager에 정의 OnQuestProgressUpdated (QuestID: Name, CurrentCount: Integer, RequiredCount: Integer) OnQuestCompleted (QuestID: Name) // 여러 시스템이 동일한 디스패처를 구독: WBP_QuestTracker → UI 갱신 BP_AchievementSys → 도전과제 확인 BP_AudioManager → 완료 사운드 재생 BP_NotificationSys → 알림 표시
설계 가이드라인

이벤트 디스패처 네이밍: On 접두사를 사용하세요 (OnHealthChanged, OnDeath, OnItemCollected).
파라미터: 구독자가 필요로 하는 최소한의 정보만 포함하세요.
호출 시점: 상태 변경이 완료된 후에 Call하세요 (값 설정 → 디스패처 Call).

SUMMARY

핵심 요약

  • 이벤트 디스패처는 옵저버 패턴을 구현하여 블루프린트 간 느슨한 결합(loose coupling)을 가능하게 한다
  • Call로 이벤트를 발생시키고, Bind로 구독, Unbind로 해제한다
  • Assign 옵션으로 Bind + Custom Event를 한 번에 생성할 수 있다
  • 파괴되는 오브젝트에서 반드시 Unbind하여 순환 참조를 방지한다
  • 체력 변경, 사망, 인벤토리 갱신, 퀘스트 진행 등 1:N 알림에 이벤트 디스패처가 적합하다
  • 디스패처 이름은 On 접두사를 사용하고, 필요한 최소한의 파라미터만 포함한다
PRACTICE

도전 과제

배운 내용을 직접 실습해보세요

실습 1: 체력 변경 이벤트 디스패처

캐릭터 BP에 OnHealthChanged 이벤트 디스패처를 생성하세요(Float 파라미터: NewHealth). 체력이 변경될 때 Call로 브로드캐스트하고, HUD 위젯에서 Bind로 구독하여 체력바를 자동 업데이트하세요.

실습 2: 문 열림 알림 시스템

Door Actor에 OnDoorOpened 디스패처를 만들고, 플레이어가 상호작용하면 Broadcast합니다. 근처의 Guard AI가 이 이벤트를 구독하여 문이 열리면 해당 위치로 이동하는 로직을 구현하세요.

심화 과제

퀘스트 시스템을 이벤트 디스패처로 구현하세요. QuestManager에 OnQuestCompleted, OnQuestFailed 디스패처를 만들고, UI, 사운드, 보상 시스템이 각각 독립적으로 구독하여 반응하는 느슨한 결합 아키텍처를 설계하세요.