게임을 만들다 보면 하나의 사건을 여러 블루프린트에 동시에 알려야 하는 상황이 자주 생깁니다. 보스를 처치했을 때 문이 열리고, 전투 음악이 멈추며, 퀘스트 UI가 갱신되는 상황이 대표적인 예입니다.
이 기능들을 보스 블루프린트에서 직접 하나씩 실행하도록 만들 수도 있지만, 연결되는 기능이 늘어날수록 보스가 문과 UI, 사운드 시스템을 모두 알고 있어야 합니다. 프로젝트가 커지면 블루프린트 사이의 의존성이 복잡해지고 수정도 어려워집니다.
이럴 때 사용할 수 있는 기능이 Event Dispatcher입니다. 이번 글에서는 Event Dispatcher의 개념부터 생성, Bind, Call, Unbind 과정과 실제 보스 처치 사례까지 순서대로 알아보겠습니다.
💡 한 줄 정답 — Event Dispatcher는 한 블루프린트에서 발생한 사건을 미리 연결된 여러 블루프린트에 동시에 알려주는 기능으로, 보스 처치·체력 변경·버튼 클릭처럼 하나의 변화에 여러 시스템이 반응해야 할 때 사용하면 블루프린트 간 연결을 단순하고 유연하게 관리할 수 있습니다.
목차
- Event Dispatcher란 무엇인가?
- 직접 함수 호출과 무엇이 다른가?
- Event Dispatcher를 만드는 방법
- Bind Event와 Call의 차이
- 보스 처치후 이벤트 실제사례
- UI에 데이터 전달하기
- Assign과 Bind Event 차이
- Unbind가 필요한 이유
- 자주 하는 실수
- Event Dispatcher를 사용하기 좋은 상황
- 끝으로…
Event Dispatcher란 무엇인가?
Event Dispatcher는 특정 사건이 발생했다는 사실을 다른 블루프린트에 전달하는 통신 기능입니다. 전달하는 쪽을 발신자, 이벤트에 연결되어 기다리는 쪽을 수신자라고 생각하면 이해하기 쉽습니다.
Epic Games 공식 문서에서는 Event Dispatcher를 하나의 액터가 이벤트를 보내고, 해당 이벤트를 듣고 있는 여러 액터가 알림을 받는 일대다 통신 방식으로 설명합니다. Epic Games Event Dispatcher 공식 가이드
예를 들어 BP_Boss가 사망했을 때 다음 기능들이 동시에 실행되어야 한다고 가정해 보겠습니다.
BP_BossDoor가 문을 연다.WB_BossHUD가 보스 체력 UI를 숨긴다.BP_CombatMusicManager가 전투 음악을 중지한다.- 퀘스트 시스템이 처치 목표를 갱신한다.
- 보상 상자가 활성화된다.
보스가 이 기능들을 직접 찾아서 호출하면 다른 블루프린트에 대한 참조가 계속 늘어납니다. Event Dispatcher를 사용하면 보스는 OnBossDied라는 이벤트만 호출하고, 나머지 블루프린트가 필요한 동작을 각각 처리하게 만들 수 있습니다.

직접 함수 호출과 Event Dispatcher의 차이
직접 함수 호출은 호출하는 블루프린트가 상대방의 참조와 함수 이름을 알아야 합니다. 플레이어가 특정 문 하나를 여는 것처럼 대상이 명확한 일대일 통신에는 간단하고 효과적입니다.
반면 Event Dispatcher는 사건을 발생시키는 블루프린트가 누가 그 사건을 듣는지 알 필요가 없습니다. 보스는 자신이 사망했다는 사실만 알리고, 문이나 UI와 같은 수신자가 해당 사건에 직접 연결됩니다.
| 구분 | 직접 함수 호출 | Event Dispatcher |
|---|---|---|
| 기본 관계 | 일대일 | 일대다 |
| 대상 참조 | 호출자가 대상 참조 필요 | 수신자가 발신자 참조 필요 |
| 호출자의 책임 | 실행할 대상을 직접 알아야 함 | 사건만 전달하면 됨 |
| 적합한 사례 | 특정 문 열기 | 보스 사망을 여러 시스템에 전달 |
| 구조 변경 | 연결 대상이 늘면 수정 증가 | 수신자를 비교적 쉽게 추가 가능 |
Event Dispatcher를 사용한다고 해서 참조가 완전히 사라지는 것은 아닙니다. 이벤트를 Bind하려면 수신자가 Dispatcher를 가진 객체의 실제 인스턴스를 알아야 합니다. 달라지는 점은 발신자가 모든 수신자를 직접 관리하지 않아도 된다는 것입니다.
액터 참조가 아직 어렵다면 이전 글인 언리얼 엔진 Actor, Pawn, Character 차이와 PlayerController 역할과 Possess 구조를 먼저 읽어보는 것을 추천합니다.

Event Dispatcher를 만드는 방법
먼저 사건을 발생시키는 블루프린트에 Dispatcher를 만들어야 합니다. 보스 처치 이벤트를 예로 들면 BP_Boss가 발신자가 됩니다.
BP_Boss를 열고 왼쪽 My Blueprint 패널을 확인합니다. Event Dispatchers 항목 옆의 + 버튼을 누른 다음 이름을 OnBossDied로 지정합니다.
이름은 사건이 발생한 상태를 나타내도록 정하는 것이 좋습니다.
OnBossDiedOnHealthChangedOnSkillUnlockedOnRoundStartedOnInteractionCompleted
BossEvent나 Dispatcher01처럼 의미를 알기 어려운 이름은 프로젝트가 커질수록 관리하기 어렵습니다. On으로 시작하고 어떤 사건인지 바로 이해할 수 있는 이름을 사용하는 방식이 편리합니다.
Dispatcher를 만든 것만으로는 아무 동작도 일어나지 않습니다. 수신자가 해당 Dispatcher에 연결하는 Bind 과정과 발신자가 실제 사건을 전달하는 Call 과정이 모두 필요합니다.
Bind Event와 Call은 역할이 다르다
Event Dispatcher를 처음 사용할 때 가장 많이 헷갈리는 부분이 Bind Event와 Call입니다.
Bind Event는 “이 Dispatcher가 호출되면 이 이벤트를 실행하겠다”라고 등록하는 과정입니다. 주로 문, UI, 사운드 매니저처럼 사건을 전달받는 수신자에서 사용합니다.
Call은 실제로 Dispatcher를 실행해 연결된 수신자들에게 사건을 전달하는 노드입니다. Dispatcher를 만든 발신자에서 사용합니다.
전체 흐름은 다음과 같습니다.
BP_Boss 사망 처리→ Call OnBossDied→ OnBossDied에 연결된 수신자들에게 전달→ 문 열기→ 보스 UI 숨기기→ 전투 음악 종료
Bind만 하고 Call하지 않으면 이벤트는 실행되지 않습니다. 반대로 Call만 하고 아무도 Bind하지 않았다면 오류가 발생하지는 않지만 반응하는 블루프린트도 없습니다.

보스 처치 후 문을 여는 실제 사례
먼저 BP_Boss에 OnBossDied Dispatcher를 생성합니다. 보스 체력이 0 이하가 되는 사망 처리 지점에서 Call OnBossDied를 실행합니다.
Apply Damage→ Current Health 계산→ Current Health <= 0→ Branch→ Call OnBossDied→ 보스 사망 애니메이션 실행
이제 BP_BossDoor에서 보스 인스턴스의 참조를 가져옵니다. 레벨에 미리 배치된 보스라면 에디터에서 참조를 지정하거나 GameMode, 레벨 관리자 등을 통해 전달받을 수 있습니다.
Event BeginPlay에서 다음과 같이 연결합니다.
Event BeginPlay→ Boss Reference 유효성 확인→ Bind Event to OnBossDied→ Custom Event: OpenBossDoor
OpenBossDoor에서는 Timeline이나 애니메이션을 실행해 문을 열어줍니다.
OpenBossDoor→ Door Timeline Play→ Set Relative Location 또는 Set Relative Rotation
같은 방식으로 보스 HUD와 음악 관리자도 OnBossDied에 연결할 수 있습니다. 문을 추가하거나 보상 상자를 활성화하더라도 BP_Boss의 사망 로직을 수정할 필요가 없습니다.
Epic Games의 공식 Quick Start 역시 보스 사망 이벤트에 문과 폭발 효과가 각각 반응하는 구조를 통해 Event Dispatcher의 일대다 통신을 설명합니다. Event Dispatchers / Delegates Quick Start Guide
Dispatcher로 UI에 데이터 전달하기
Event Dispatcher는 사건만 전달하는 것이 아니라 필요한 데이터도 함께 전달할 수 있습니다.
보스의 체력이 변경될 때 UI에 현재 체력과 최대 체력을 보내고 싶다면 OnHealthChanged Dispatcher를 만든 다음 입력값을 추가합니다.
CurrentHealth: FloatMaxHealth: Float
피해 처리 후 다음과 같이 호출합니다.
CurrentHealth 갱신→ Call OnHealthChanged CurrentHealth 전달 MaxHealth 전달
보스 HUD는 OnHealthChanged에 이벤트를 Bind한 뒤 전달받은 값으로 Progress Bar를 갱신합니다.
Event UpdateBossHealth→ CurrentHealth / MaxHealth→ Set Percent
이 구조를 사용하면 UI가 Event Tick에서 보스 체력을 매 프레임 확인하지 않아도 됩니다. 체력이 실제로 변경됐을 때만 UI가 갱신되기 때문에 이전 글에서 다룬 Event Tick 남발 문제도 줄일 수 있습니다.
내부 링크 문장 예시:
UI 값을 매 프레임 확인하고 있다면 언리얼 엔진 Event Tick을 남발하면 안 되는 이유에서 이벤트 기반 구조와 성능 차이를 먼저 확인해 보세요.
Assign과 Bind Event의 차이
Dispatcher 참조에서 노드를 검색하면 Bind Event 외에 Assign도 볼 수 있습니다.
Assign OnBossDied를 사용하면 Bind 노드와 연결할 이벤트 노드가 함께 생성됩니다. 빠르게 이벤트 하나를 연결할 때 편리합니다.
Bind Event to OnBossDied는 연결할 Custom Event를 직접 만들고 지정하는 방식입니다. 이벤트의 이름과 위치를 원하는 대로 정리할 수 있어 복잡한 그래프에서는 Bind Event가 더 명확할 수 있습니다.
두 방식 모두 Dispatcher에 이벤트를 연결한다는 기본 목적은 같습니다.
- 빠르게 하나의 이벤트를 연결할 때:
Assign - Custom Event를 명확하게 관리할 때:
Bind Event - 여러 위치에서 연결 관계를 관리할 때:
Bind Event권장 - 연결 해제까지 직접 관리할 때:
Bind Event와Unbind Event
초보자는 Assign으로 구조를 먼저 익힌 뒤, 프로젝트가 복잡해지면 Bind와 Unbind를 명시적으로 관리하는 방식으로 발전해도 괜찮습니다.

Unbind가 필요한 이유
이벤트를 Bind한 뒤 수신자나 화면의 수명이 끝났다면 필요에 따라 연결을 해제해야 합니다.
UMG 위젯이 생성될 때마다 Dispatcher에 다시 Bind되는데 기존 연결을 해제하지 않으면 같은 이벤트가 중복으로 실행될 수 있습니다. 버튼을 한 번 눌렀는데 UI 갱신이 두 번 또는 세 번 실행되는 문제가 대표적입니다.
위젯에서는 다음과 같은 흐름을 사용할 수 있습니다.
Event Construct 또는 On Initialized→ Bind Event to OnHealthChangedEvent Destruct→ Unbind Event from OnHealthChanged
액터라면 BeginPlay에서 Bind하고 EndPlay에서 Unbind하는 방식으로 정리할 수 있습니다.
무조건 모든 Dispatcher를 직접 해제해야 한다는 뜻은 아닙니다. 객체 수명과 참조 관계에 따라 자동으로 정리되는 경우도 있지만, 위젯을 반복 생성하거나 동일한 객체가 여러 번 Bind될 가능성이 있다면 직접 연결을 관리하는 편이 안전합니다.
또한 하나의 이벤트만 제거하려면 Unbind Event, 해당 Dispatcher에 연결된 이벤트를 모두 제거하려면 Unbind All Events를 사용합니다. Unbind All Events는 다른 시스템이 등록한 이벤트까지 해제할 수 있으므로 사용 범위를 신중하게 확인해야 합니다.
자주 하는 실수
첫 번째 실수는 Dispatcher를 만들고 Call만 실행하는 것입니다. 수신자에서 Bind하지 않았다면 아무 일도 일어나지 않습니다.
두 번째는 Bind 대상 인스턴스를 잘못 가져오는 것입니다. 클래스 자체가 아니라 현재 레벨에서 사용 중인 실제 보스 인스턴스에 Bind해야 합니다. 잘못된 객체나 None 상태의 참조를 사용하면 이벤트가 연결되지 않습니다.
세 번째는 Bind 시점이 너무 늦는 경우입니다. 보스가 먼저 사망한 뒤 문이 Dispatcher에 Bind하면 이미 발생한 이벤트를 다시 받을 수 없습니다. 수신자는 사건이 발생하기 전에 Bind를 완료해야 합니다.
네 번째는 위젯을 열 때마다 중복 Bind하는 것입니다. Event Construct는 위젯의 사용 방식에 따라 여러 번 실행될 수 있으므로 이미 연결되어 있는지 확인하거나 Destruct에서 Unbind하는 구조가 필요합니다.
다섯 번째는 모든 통신을 Event Dispatcher로 처리하는 것입니다. 특정 액터 하나의 함수만 실행하면 되는 상황에서는 직접 참조가 더 단순할 수 있습니다. 여러 종류의 객체에 같은 명령을 전달해야 한다면 Blueprint Interface가 더 적합할 수도 있습니다.
Event Dispatcher를 사용하기 좋은 상황
Event Dispatcher는 다음과 같은 상황에서 특히 유용합니다.
- 보스가 사망하면 문, UI, 음악과 보상이 동시에 반응할 때
- 플레이어 체력이 변경될 때 HUD를 갱신할 때
- 스킬이 해금되면 여러 UI 버튼을 새로고침할 때
- 라운드가 시작되거나 종료될 때 관련 시스템에 알릴 때
- 인벤토리가 변경될 때 가방과 장비 UI를 갱신할 때
- 버튼 클릭 결과를 부모 위젯에 전달할 때
- 퀘스트 상태가 바뀌었음을 여러 시스템에 알릴 때
반대로 다음 상황에서는 다른 통신 방식을 먼저 고려할 수 있습니다.
- 대상 하나가 명확하다: 직접 함수 호출
- 서로 다른 클래스에 같은 기능을 요청한다: Blueprint Interface
- 모든 플레이어가 공유해야 하는 상태다: GameState 또는 PlayerState
- 네트워크의 다른 클라이언트에도 전달해야 한다: RPC와 Replication
Event Dispatcher는 네트워크 복제를 자동으로 처리하는 기능이 아닙니다. 멀티플레이 게임에서는 서버에서 상태를 변경하고 Replication이나 RPC로 전달한 뒤, 각 클라이언트에서 Dispatcher를 이용해 UI와 로컬 시스템에 알리는 구조가 필요합니다.
끝으로…
Event Dispatcher는 블루프린트 사이의 연결을 줄이고 하나의 사건에 여러 시스템이 반응하도록 만드는 데 유용합니다.
핵심 흐름은 어렵지 않습니다.
발신자에서 Dispatcher 생성→ 수신자가 발신자 참조 확보→ 수신자가 Dispatcher에 Bind→ 발신자가 필요한 순간 Call→ 수신자의 이벤트 실행→ 필요하면 Unbind
처음에는 OnBossDied처럼 결과가 분명한 이벤트부터 연습하는 것이 좋습니다. 보스가 죽으면 문과 UI가 동시에 반응하도록 만든 뒤, 체력 변경이나 스킬 해금처럼 데이터를 함께 전달하는 구조로 확장하면 Event Dispatcher의 장점을 쉽게 이해할 수 있습니다.
다음 글에서는 Event Dispatcher를 사용하다가 자주 만나게 되는 Accessed None 오류의 원인과 해결 방법을 실제 블루프린트 참조 구조와 함께 알아보겠습니다.
참고 사이트
- Event Dispatchers / Delegates Quick Start Guide
Epic Games에서 제공하는 공식 가이드입니다. 보스가 사망했을 때 문과 폭발 효과가 동시에 반응하는 예제로 Event Dispatcher의 일대다 통신 구조를 확인할 수 있습니다. - Direct Actor Communication Quick Start Guide
특정 액터의 참조를 가져와 함수를 직접 호출하는 방법을 설명합니다. Event Dispatcher와 직접 통신의 차이를 비교할 때 도움이 됩니다. - Implementing Blueprint Interfaces
서로 다른 종류의 블루프린트가 같은 기능을 구현하도록 만드는 Blueprint Interface의 공식 문서입니다.