이벤트 디스패처의 기본 사용법
이벤트 디스패처를 선언·바인딩·호출해 한 액터의 변화를 여러 수신자에게 느슨하게 전달하는 법을 익힙니다.
지난 절에서 다룬 직접 참조 통신은 간단하고 명확하지만, 호출 측이 대상 블루프린트의 구체 타입을 알아야 하는 강한 결합(Tight Coupling) 문제가 있습니다.
이 구조는 확장성과 유지보수성에 부담을 줄 수 있습니다.
이번 절에서는 이 문제를 줄이고 느슨한 결합(Loose Coupling)을 가능하게 하는 통신 기법, 이벤트 디스패처(Event Dispatcher)를 다룹니다.
이벤트 디스패처란 무엇인가?
이벤트 디스패처는 특정 이벤트가 발생했음을 알리는 신호기와 같습니다.
신호를 받을 블루프린트는 실행할 이벤트를 Bind로 등록합니다. Assign은 이벤트 생성과 바인딩을 함께 구성하는 편의 방식이며, Bind 뒤에 반드시 추가하는 별도 단계는 아닙니다.
즉, 이벤트 디스패처는 “어떤 일이 일어났을 때 알려주겠다”는 신호를 보냅니다.
수신자는 이 신호를 받기 위해 미리 등록합니다.
이 방식은 직접 참조와 달리, 신호를 보내는 로직이 각 수신자의 구체 타입이나 처리 내용을 직접 알 필요를 줄여 줍니다. 바인딩에는 실행 대상과 이벤트가 연결되며, 수신자는 등록할 디스패처 소유자의 참조를 알아야 합니다.
그저 특정 신호를 발생시킨다는 사실만 알면 됩니다.
이벤트 디스패처의 핵심 개념- 생성 (Create): 이벤트를 알릴 디스패처를 정의합니다.
- 바인드 (Bind): 특정 블루프린트가 디스패처에 나는 이 신호를 들을 준비가 되었어라고 등록합니다.
- 호출 (Call / Dispatch): 디스패처를 소유한 블루프린트가 신호를 발생시킨다는 의미로 디스패처를 호출합니다.
- 언바인드 (Unbind): 더 이상 신호를 듣고 싶지 않을 때 등록을 해제합니다.
이벤트 디스패처 생성 및 정의
이벤트 디스패처는 특정 액터 블루프린트 내부에 정의됩니다.
예를 들어, BP_Door가 열릴 때 다른 액터들에게 알리고 싶다면, BP_Door 내부에 디스패처를 만듭니다.
액터 블루프린트 열기: BP_Door 블루프린트 에디터를 엽니다. (예시를 위해 새롭게 BP_Door 액터 블루프린트를 만들어 봅시다.)
- 좌측 변수(Variables) 패널 아래의 이벤트 디스패처(Event Dispatchers) 패널로 이동합니다.
- 패널 상단의
+ 이벤트 디스패처(+ Event Dispatcher)버튼을 클릭합니다. - 이름을 지정합니다. (예:
OnDoorOpened)
- 생성된
OnDoorOpened디스패처를 선택합니다. - 디테일 패널에서
입력(Inputs)섹션을 찾아+버튼을 클릭합니다. - 예를 들어, 문을 연 액터가 누구인지 함께 알리고 싶다면
OpeningActor(Actor Reference 타입)라는 입력 매개변수를 추가할 수 있습니다. - 이렇게 정의된 매개변수는 디스패처가 호출될 때 함께 전달됩니다.
컴파일 및 저장: 디스패처를 정의한 후에는 블루프린트를 컴파일하고 저장합니다.
이벤트 디스패처 호출(Call)하기
디스패처를 호출하는 것은 신호를 발생시킨다는 의미입니다.
디스패처를 호출하면 현재 바인드된 이벤트들이 호출됩니다. 병렬 실행이나 수신자 간 호출 순서를 보장하는 기능은 아니므로, 순서에 의존하는 작업은 명시적인 호출 흐름으로 구성합니다.
호출 노드 배치BP_Door블루프린트의 이벤트 그래프로 이동합니다.- 만약 문을 여는
OpenDoor함수(Function)가 있다면 그 함수 로직의 끝에, 또는Event Interact로직의 특정 시점에 디스패처를 호출하도록 연결합니다. - 좌측 이벤트 디스패처 패널에서
OnDoorOpened디스패처를 드래그하여 그래프에 놓으면,Call OnDoorOpened(또는Dispatch OnDoorOpened) 노드가 생성됩니다. - 이 노드를 문이 열리는 로직의 적절한 위치에 실행 핀으로 연결합니다.
- 만약
OpeningActor입력 매개변수가 있다면, 이 노드의 해당 핀에 문을 연 액터의 레퍼런스를 연결해 줍니다.
이벤트 디스패처에 바인드(Bind)하기
이제 다른 블루프린트(예: BP_PlayerCharacter 또는 BP_GameManager)가 BP_Door의 OnDoorOpened 이벤트를 듣고 반응하도록 바인드해 봅시다.
듣고 싶은 블루프린트 열기: BP_GameManager 또는 BP_PlayerCharacter 블루프린트를 엽니다.
편의상 BP_GameManager를 새로 만들어 사용해 봅시다.
부모 클래스는 Actor로 생성합니다.
- 이 블루프린트가
BP_Door액터 인스턴스를 알아야 바인드할 수 있습니다. 가장 간단한 방법은Event BeginPlay에서Get All Actors Of Class노드를 사용하여 월드의BP_Door액터를 가져오는 것입니다. - 주의: 배열이 비어 있지 않은지 확인하고 원하는 문을 선택하거나,
For Each Loop로 모든 문에 바인드합니다. 첫 요소의 순서를 특정 문 선택 기준으로 삼지 않습니다. - 가져온
BP_Door액터 레퍼런스를 변수(예:MyDoorRef, BP_Door Object Reference 타입)로 승격시켜 저장해 두면 편리합니다.
BP_GameManager블루프린트의Event BeginPlay뒤에, 또는 적절한 초기화 로직 뒤에, 앞서 가져온MyDoorRef변수(Get 노드)의 출력 핀에서 드래그하여Bind Event to OnDoorOpened노드를 검색하고 선택합니다.MyDoorRef가 유효한 경우에만 바인드를 실행하고Target핀에 연결합니다.Event핀에는 디스패처가 호출될 때 실행될커스텀 이벤트(Custom Event)를 연결해야 합니다.
Bind Event to OnDoorOpened노드의Event핀에서 드래그하여Custom Event를 검색하고Add Custom Event를 선택합니다.- 새로운 커스텀 이벤트 노드가 생성됩니다. 이름을
HandleDoorOpenEvent와 같이 지정합니다. - 만약
OnDoorOpened디스패처에OpeningActor와 같은 입력 매개변수가 있었다면, 이 커스텀 이벤트 노드에도 자동으로 해당 매개변수 핀이 생성됩니다. - 이제
HandleDoorOpenEvent노드의 실행 핀 뒤에 디스패처 신호를 받았을 때 수행할 로직을 구현합니다. - 예시:
Print String노드를 연결하여 게임 매니저: 문이 열렸습니다! 연 사람: 을 출력하고,OpeningActor가 유효하면Get Display Name으로 문자열을 얻어Append에 연결합니다. 유효하지 않다면 “알 수 없음” 같은 대체 문구를 사용합니다.
컴파일 및 저장: 두 블루프린트(BP_Door와 BP_GameManager)를 모두 컴파일하고 저장합니다.
- 언리얼 엔진 메인 에디터로 돌아와
BP_Door액터와BP_GameManager액터를 월드에 배치합니다. - 게임을 플레이하고
BP_Door액터의 문이 열리도록 상호작용합니다. (예:BP_Door의Interact인터페이스를 구현하고 플레이어 캐릭터에서E키를 눌렀을 때Interact메시지를 보내도록 설정) - 문이 열리는 순간,
BP_GameManager블루프린트에 바인드된 커스텀 이벤트가 실행되어 게임 매니저: 문이 열렸습니다! 메시지가 출력되는 것을 확인할 수 있습니다.
바인드 전에 발생한 알림은 나중에 등록한 수신자에게 재전달되지 않습니다. 액터 간 BeginPlay 호출 순서에 기대지 말고, 등록을 마친 뒤 문 열기 같은 사건을 허용하거나 현재 상태를 별도로 읽어 초기화하세요.
문 움직임과 입력을 아직 만들지 않았다면 등록·알림부터 확인합니다. BP_Door에 출력 없는 OpenDoor를 만들고, 그 함수에서 문구 출력 → Call OnDoorOpened를 연결합니다. OpeningActor 입력을 사용하는 경우 OpenDoor에도 같은 입력을 추가해 전달합니다. BP_GameManager에서 유효한 MyDoorRef를 저장하고 Bind를 마친 실행 출력 뒤에 MyDoorRef의 OpenDoor를 한 번 호출합니다. 입력에는 매니저의 Self를 넣습니다. 두 액터를 배치·저장하고 Play하면 등록된 HandleDoorOpenEvent의 출력 한 번을 확인할 수 있습니다. 이 순서는 다른 액터의 BeginPlay 순서에 기대지 않습니다. 확인 뒤에는 원래 상호작용 경로로 사건을 일으키세요.
늦게 등록한 수신자 예상하기
디스패처를 한 번 Call한 뒤, 수신자 A와 B의 서로 다른 이벤트를 각각 한 번 Bind하고 다시 한 번 Call했습니다. 수신자 내부의 다른 호출이나 중복 등록은 없습니다. A와 B는 각각 몇 번 반응할까요?
현재 등록 목록으로 판단하기
각각 한 번입니다. 첫 Call 당시에는 두 수신자가 등록되지 않았으므로 받지 못하고, 등록 뒤 두 번째 Call만 전달됩니다. 이전 알림을 다시 받는 기능과 현재 상태를 읽는 기능은 별도로 구성해야 합니다. A와 B 중 어느 이벤트가 먼저 호출되는지는 이 조건으로 정하지 않습니다.
같은 대상·이벤트의 중복 바인딩은 한 번만 등록되지만 서로 다른 이벤트는 여러 개 등록할 수 있습니다. 수신을 끝낼 때는 자신의 이벤트를 Unbind Event로 해제합니다. Unbind All Events는 같은 디스패처의 다른 구독자에게도 영향을 주므로 구분해서 사용하세요.
이벤트 디스패처의 장점
- 느슨한 결합(Loose Coupling): 문을 여는 로직에서 게임 매니저·사운드 매니저의 구체적인 처리 함수를 직접 호출하지 않아도 됩니다.
- 유연성: 하나의 디스패처에 여러 개의 다른 블루프린트가 바인드될 수 있습니다. (예: 문이 열릴 때 게임 매니저도 알고, 사운드 매니저도 알고, 이펙트 매니저도 아는 등)
- 확장성: 나중에 새로운 액터가 문이 열리는 이벤트를 듣고 싶으면, 해당 액터에서
Bind Event노드만 추가하면 됩니다. 기존 문 블루프린트를 수정할 필요가 없습니다.
디스패처를 사용할 때는 생성과 호출뿐 아니라 바인드한 수신자가 언제 해제되는지까지 함께 보면 흐름이 더 안정적입니다.
아래 그림은 문 인스턴스에 두 수신자가 미리 바인드된 상태를 보여줍니다.
등록된 수신자에게 알림 전달
본문의 Bind·Call·Unbind에서 현재 등록 집합이 바뀌는 점을 보여 주어 등록 전 알림이 재생되지 않으며 해제가 필요하다는 점을 드러낸다. 두 수신자는 같은 알림 단계에 묶고 호출 순서를 만들지 않는다.
BOUND EVENTS · ONE OWNER
등록을 마친 수신자에게 문 열림을 알립니다
두 수신자가 이 문 인스턴스의 OnDoorOpened에 미리 바인드된 상태입니다. Call은 현재 등록된 이벤트들을 호출하며 수신자 순서나 병렬 실행을 보장하지 않습니다.
화살표는 바인딩을 마친 뒤의 알림 호출입니다. 화살표의 배치는 호출 순서나 병렬 실행을 뜻하지 않습니다.
등록과 해제도 설계합니다
등록 전 발생한 알림은 재전달되지 않습니다. 각 수신자는 문 참조를 얻어 바인드하고, 수신을 끝낼 때 자신의 이벤트를 해제합니다.
이 예의 조건
- 본문과 원 도표에 제시된 사례의 입력·조건을 사용합니다. 설명용 수치나 독립 비교 경로는 각 단계에 표시합니다.
- 현재 상태·값과 전환 근거의 위치는 모든 단계에서 같습니다. 조건이 맞지 않거나 실행되지 않은 경로를 성공한 동작으로 해석하지 않습니다.
| 관찰·상황 | 값·보충 정보 | 변화·이유 |
|---|---|---|
| 등록 Bind로 현재 수신자 집합을 만든다. |
|
|
| 알림 호출 Call이 현재 두 수신자에게 같은 알림을 전달한다. |
|
|
| 해제 Unbind 뒤 수신자는 다음 알림 대상에서 빠진다. |
|
|
등록된 수신자에게 알림 전달
본문의 Bind·Call·Unbind에서 현재 등록 집합이 바뀌는 점을 보여 주어 등록 전 알림이 재생되지 않으며 해제가 필요하다는 점을 드러낸다. 두 수신자는 같은 알림 단계에 묶고 호출 순서를 만들지 않는다.
BOUND EVENTS · ONE OWNER
등록을 마친 수신자에게 문 열림을 알립니다
두 수신자가 이 문 인스턴스의 OnDoorOpened에 미리 바인드된 상태입니다. Call은 현재 등록된 이벤트들을 호출하며 수신자 순서나 병렬 실행을 보장하지 않습니다.
화살표는 바인딩을 마친 뒤의 알림 호출입니다. 화살표의 배치는 호출 순서나 병렬 실행을 뜻하지 않습니다.
등록과 해제도 설계합니다
등록 전 발생한 알림은 재전달되지 않습니다. 각 수신자는 문 참조를 얻어 바인드하고, 수신을 끝낼 때 자신의 이벤트를 해제합니다.
이 예의 조건
- 본문과 원 도표에 제시된 사례의 입력·조건을 사용합니다. 설명용 수치나 독립 비교 경로는 각 단계에 표시합니다.
- 현재 상태·값과 전환 근거의 위치는 모든 단계에서 같습니다. 조건이 맞지 않거나 실행되지 않은 경로를 성공한 동작으로 해석하지 않습니다.
| 관찰·상황 | 값·보충 정보 | 변화·이유 |
|---|---|---|
| 등록 Bind로 현재 수신자 집합을 만든다. |
|
|
| 알림 호출 Call이 현재 두 수신자에게 같은 알림을 전달한다. |
|
|
| 해제 Unbind 뒤 수신자는 다음 알림 대상에서 빠진다. |
|
|
이벤트 디스패처는 복잡한 게임 시스템에서 블루프린트 간의 통신을 관리하는 데 매우 강력하고 유연한 방법입니다.
특히, 특정 사건 발생 시 여러 대상에게 알림이 필요한 경우에 최적의 솔루션입니다.
이번 절에서는 이벤트 디스패처의 기본 개념과 생성, 호출, 바인드 방법에 대해 알아보았습니다.
직접 참조의 한계를 극복하고 블루프린트 간의 느슨한 결합을 구현하는 중요한 통신 기법입니다.