간단한 이벤트 핸들러 설정
파티클 소멸 이벤트를 발생·수신하는 이미터를 연결해 원본 파티클이 사라질 때 폭발 파티클을 생성합니다.
불꽃놀이의 폭죽은 하늘로 올라가다가 사라지는 순간 그 자리에서 터집니다. 이런 효과를 만들려면 올라가는 입자를 만드는 이미터와 터지는 입자를 만드는 이미터가 서로 알려야 합니다. 지금까지 다룬 스폰 모듈과 Particle Update 모듈은 이미터 하나 안에서만 동작하므로, 다른 이미터에서 일어난 일에 반응하려면 다른 방법이 필요합니다. 이 글에서는 한 이미터가 만든 이벤트를 같은 시스템의 다른 이미터가 받는 이벤트 핸들러(Event Handler)를 설정해, 입자가 사라지는 자리에 새 입자를 만들어 봅니다.
이벤트 핸들러를 간단히 말하면 "A라는 일이 생기면 B를 하라"고 파티클 시스템에 알려 주는 방법입니다. 다만 이 방식은 CPU에서 시뮬레이션하는 이미터끼리만 쓸 수 있고 GPU 시뮬레이션에서는 동작하지 않으며, 게임 코드로 결과를 돌려보내는 콜백과도 다른 기능입니다.
이벤트 핸들러가 하는 일
이벤트 핸들러는 입자의 충돌이나 소멸 같은 일이 생겼을 때, 미리 정해 둔 동작을 하도록 이미터들을 연결하는 기능입니다. 이를 이용하면 이미터 사이의 상호작용을 만들거나, 입자의 상태가 바뀔 때 새로운 효과를 일으킬 수 있습니다. 주로 다음과 같은 경우에 씁니다.
- 입자가 사라질 때: 입자가 수명을 다해 사라지는 자리에 폭발이나 잔해 입자를 만듭니다.
- 입자가 부딪힐 때: 입자가 월드나 다른 물체와 충돌하면 스파크나 파편을 더 만듭니다. 소리를 내려면 오디오를 따로 연결해야 합니다.
- 특정 값에 도달할 때: 입자의 속도나 크기가 정한 값을 넘으면 이벤트를 만들도록 직접 조건을 설계하고, 그 이벤트로 다른 입자를 만듭니다.
이벤트 핸들러는 두 부분으로 이루어집니다. 하나는 조건이 맞을 때 이벤트를 만드는 이벤트 발생기(Event Generator)로, 원본 이미터의 Particle Update 그룹에 주로 둡니다. 다른 하나는 그 이벤트를 받아 정해 둔 동작을 하는 이벤트 수신기(Event Receiver)로, 받는 이미터의 Event Handler 그룹에 Receive 계열의 모듈을 둡니다. 가장 흔한 예인 "입자가 사라질 때 다른 입자 만들기"로 기본 사용법을 익혀 보겠습니다.
원본 이미터에서 소멸 이벤트 만들기
앞에서 만든 NS_BasicSpawn을 확장해, 입자가 수명을 다해 사라질 때 작은 폭발 입자가 생기게 해 봅니다. 소멸 이벤트에는 Generate Death Event 모듈을 씁니다. 이름이 비슷한 Generate Location Event는 살아 있는 입자의 위치를 보내는 용도이므로 소멸을 알리는 것과는 다릅니다.
먼저 NS_BasicSpawn을 열고 기존 이미터의 Sim Target이 CPU인지 확인합니다. 그리고 Emitter Properties에서 Requires Persistent IDs를 켭니다. 이벤트를 주고받으려면 입자마다 프레임이 바뀌어도 변하지 않는 고유 ID가 필요하기 때문입니다. 다음으로 Particle Update에 수명이 다한 입자를 없애는 Particle State가 있는지 확인하고, 같은 그룹에 Generate Death Event를 추가합니다. 모듈을 놓을 위치는 에디터의 의존 관계 안내를 따릅니다.
마지막으로 원본 입자의 Lifetime과 움직임을 확인합니다. 이벤트가 언제 어디서 생기는지 눈으로 구별하기 쉽도록, Spawn Rate를 낮은 값으로 두고 시작하는 편이 좋습니다.
받는 이미터 만들기
이제 이벤트를 받아 폭발 입자를 만들 이미터를 더합니다. 시스템 개요(System Overview)를 오른쪽 클릭해 Add Emitter에서 Simple Sprite Burst 템플릿을 추가하고, 이름을 BurstOnDeath로 바꿉니다. 이 이미터도 CPU 시뮬레이션을 씁니다. 이미터를 고르는 창의 버튼 이름은 엔진 버전에 따라 다를 수 있습니다.
이 이미터는 이벤트를 받을 때만 입자를 만들어야 합니다. 그래서 먼저 BurstOnDeath의 Emitter Update에서 템플릿에 들어 있는 Spawn Burst Instantaneous나 Spawn Rate를 지우거나 끕니다. 그리고 Emitter State와 System State는 이벤트를 기다리는 동안 이 이미터가 계속 켜져 있도록 설정합니다. 받는 이미터가 먼저 끝나 버리면 그 뒤에 온 이벤트는 처리되지 않습니다.
다음으로 Add Event Handler로 Event Handler 그룹을 더합니다. 그룹의 Event Handler Properties에서 Source를 열고 원본 이미터와 그 이미터의 Death 이벤트를 고릅니다. 이름을 직접 입력하는 것이 아니라 드롭다운에서 실제 발생기를 선택해야 합니다. Execution Mode는 Spawned Particles로 두어 이 이벤트로 새로 만든 입자에만 이벤트 스크립트가 실행되게 하고, Spawn Number를 1로 두고 Random Spawn Number는 끕니다. 이는 처리한 이벤트 하나마다 새 입자를 한 개 만든다는 뜻이며, 나이아가라 시스템을 하나씩 따로 만든다는 뜻이 아닙니다.
그다음 같은 Event Handler 그룹에 Receive Death Event를 추가해, 소멸 이벤트에 담긴 위치 같은 값을 받습니다. 이때 두 이미터의 좌표 공간과 속도를 물려받는 설정도 확인해야 새 입자가 엉뚱한 자리에 생기지 않습니다. 마지막으로 Particle Spawn의 Initialize Particle에서 Lifetime을 0.5, 스프라이트 크기를 20.0, 색을 주황색이나 노란색으로 두고, Particle Update의 Particle State와 Render의 Sprite Renderer, 머티리얼도 확인합니다.
연결이 동작하는 모습
소멸 이벤트에 반응하는 두 이미터
원본 CPU 입자 수명 종료→Death 데이터→활성 수신 Handler 처리→Spawn Number 1 새 입자 0.5초라는 실제 사건/수명 전이 과정이다. 처리 한도·Persistent IDs를 보존한다.
NIAGARA · CH3-3
CPU 소멸 이벤트로 수신 이미터의 입자를 만듭니다
한 시스템 안의 원본 CPU 이미터가 Death 이벤트 데이터를 만들고, 수신 CPU 이미터의 Event Handler가 이를 처리합니다. 처리된 이벤트당 Spawn Number 1을 사용하는 본문 예입니다.
별도 시스템 생성 아님
원본에는 Persistent IDs가 필요하고 수신 이미터는 이벤트를 처리할 동안 활성 상태여야 합니다. 처리 한도에 걸리면 일부 이벤트가 누락될 수 있습니다. 별도 Niagara System 생성이나 게임·오디오 콜백은 이 흐름에 자동으로 포함되지 않습니다.
이 예의 조건
- 본문과 원 도표에 제시된 사례의 입력·조건을 사용합니다. 설명용 수치나 독립 비교 경로는 각 단계에 표시합니다.
- 현재 상태·값과 전환 근거의 위치는 모든 단계에서 같습니다. 조건이 맞지 않거나 실행되지 않은 경로를 성공한 동작으로 해석하지 않습니다.
관계도의 보충 설명
| 범위 | 원문 |
|---|---|
| 관계·조건 설명 | 원본 CPU 이미터의 Generate Death Event→수신 CPU 이미터 Event Handler의 Source/Spawned Particles/Spawn Number 1/Receive Death Event→처리된 이벤트당 새 입자 1개를 나타낸다. 같은 시스템 안의 처리이며 템플릿을 독립적으로 생성하는 경로는 포함하지 않는다. |
| 관찰·상황 | 값·보충 정보 | 변화·이유 |
|---|---|---|
| CPU 입자 종료 원본 입자의 수명이 끝난다. |
|
|
| Handler 처리 활성 수신자가 Death 데이터를 처리한다. |
|
|
| 새 입자 Spawn Spawn Number 1로 수명 0.5초 입자를 만든다. |
|
|
소멸 이벤트에 반응하는 두 이미터
원본 CPU 입자 수명 종료→Death 데이터→활성 수신 Handler 처리→Spawn Number 1 새 입자 0.5초라는 실제 사건/수명 전이 과정이다. 처리 한도·Persistent IDs를 보존한다.
NIAGARA · CH3-3
CPU 소멸 이벤트로 수신 이미터의 입자를 만듭니다
한 시스템 안의 원본 CPU 이미터가 Death 이벤트 데이터를 만들고, 수신 CPU 이미터의 Event Handler가 이를 처리합니다. 처리된 이벤트당 Spawn Number 1을 사용하는 본문 예입니다.
별도 시스템 생성 아님
원본에는 Persistent IDs가 필요하고 수신 이미터는 이벤트를 처리할 동안 활성 상태여야 합니다. 처리 한도에 걸리면 일부 이벤트가 누락될 수 있습니다. 별도 Niagara System 생성이나 게임·오디오 콜백은 이 흐름에 자동으로 포함되지 않습니다.
이 예의 조건
- 본문과 원 도표에 제시된 사례의 입력·조건을 사용합니다. 설명용 수치나 독립 비교 경로는 각 단계에 표시합니다.
- 현재 상태·값과 전환 근거의 위치는 모든 단계에서 같습니다. 조건이 맞지 않거나 실행되지 않은 경로를 성공한 동작으로 해석하지 않습니다.
관계도의 보충 설명
| 범위 | 원문 |
|---|---|
| 관계·조건 설명 | 원본 CPU 이미터의 Generate Death Event→수신 CPU 이미터 Event Handler의 Source/Spawned Particles/Spawn Number 1/Receive Death Event→처리된 이벤트당 새 입자 1개를 나타낸다. 같은 시스템 안의 처리이며 템플릿을 독립적으로 생성하는 경로는 포함하지 않는다. |
| 관찰·상황 | 값·보충 정보 | 변화·이유 |
|---|---|---|
| CPU 입자 종료 원본 입자의 수명이 끝난다. |
|
|
| Handler 처리 활성 수신자가 Death 데이터를 처리한다. |
|
|
| 새 입자 Spawn Spawn Number 1로 수명 0.5초 입자를 만든다. |
|
|
위 그림은 소멸 이벤트에 반응하는 두 이미터의 관계를 보여 줍니다. 왼쪽의 원본 이미터는 CPU 시뮬레이션과 Persistent IDs를 쓰며, Particle State가 수명이 다한 입자를 없앨 때 Generate Death Event가 위치 같은 데이터를 담은 Death 이벤트를 만듭니다. 이 이벤트는 같은 시스템 안의 BurstOnDeath 이미터로 전달되는데, 받는 쪽에서는 Event Handler의 Source가 그 이벤트를 고르고, Spawned Particles와 Spawn Number 1 설정에 따라 새 입자를 만들며, Receive Death Event가 받은 위치를 그 입자에 채웁니다. 그림의 같은 칸에 적힌 초기 색과 0.5초 수명은 이벤트에서 받은 값이 아니라, 앞에서 Particle Spawn의 Initialize Particle에 넣은 값입니다. 결과는 처리된 이벤트 하나마다 새 입자 한 개입니다.
그림 아래의 설명은 이 흐름이 동작하기 위한 조건을 다시 짚습니다. 원본에는 Persistent IDs가 필요하고, 받는 이미터는 이벤트를 처리하는 동안 켜져 있어야 하며, 처리 한도에 걸리면 일부 이벤트가 빠질 수 있습니다. 또 이 흐름은 별도의 나이아가라 시스템을 만들거나 게임, 오디오 쪽 콜백을 자동으로 부르지 않습니다. 단계 그림은 같은 흐름을 원본 입자의 수명 종료, 이벤트 전달, 받는 이미터의 새 입자 생성 순서로 나누어 보여 줍니다.
연결이 제대로 되었다면 원본 입자가 수명을 다한 자리마다 짧게 살다 사라지는 새 입자가 한 개씩 생깁니다. 템플릿에 남아 있던 생성 모듈 때문에 원점에서 따로 버스트가 터지는 것과, 이벤트에 반응해 생기는 입자를 구분해서 봅니다.
이벤트의 수와 새 입자의 수도 구별해야 합니다. 원본에서 소멸 이벤트가 5개 생기고 받는 이미터가 이 5개를 모두 처리했다고 해 봅시다. Random Spawn Number를 끄고 Spawn Number를 1로 두었다면 새 입자는 5 × 1 = 5개입니다. 나이아가라 시스템이 다섯 개 새로 생기는 것이 아닙니다. 그리고 받는 이미터가 꺼져 있었거나 프레임당 처리 한도를 넘었다면, 생긴 이벤트의 수를 그대로 곱할 수 없습니다. Max Events Per Frame은 이벤트 핸들러가 한 프레임에 처리할 이벤트의 수이며, 이보다 많이 생긴 이벤트는 무시됩니다.
다른 곳에 쓰는 방법
충돌에 반응하는 효과도 같은 방식으로 만듭니다. 원본 이미터에서 Collision의 결과를 Generate Collision Event로 보내고, 받는 이미터에서 Receive Collision Event로 받습니다.
블루프린트나 C++에서 효과를 제어하는 것은 이와 다른 경로입니다. 사용자 파라미터나 지원되는 데이터 전달 기능으로 효과에 값을 넘길 수 있지만, 이것을 이 글의 CPU 이미터 사이 이벤트 핸들러와 같은 설정으로 취급하지 않습니다. 특정 값에 도달할 때 이벤트를 만드는 경우도, 어떤 조건에서 이벤트를 만들고 어떤 데이터를 담을지를 직접 설계해야 합니다. 그런 이름의 표준 모듈이 있으리라 가정하고 검색하는 것으로 끝나지 않습니다.
이벤트 연결이 동작하지 않으면 다음 순서로 확인합니다. 반응이 아예 없다면 두 이미터가 CPU 시뮬레이션인지, 원본에 Persistent IDs가 켜져 있는지, 입자가 실제로 수명을 다해 사라지는지, Source가 올바른 이벤트를 가리키는지 봅니다. 새 입자가 엉뚱한 자리에 생긴다면 좌표 공간과 Receive 모듈을, 너무 많이 생긴다면 이벤트당 Spawn Number와 처리 한도를 확인합니다.
더 깊이: 이벤트를 쓰기 전에 비교할 것
이벤트는 CPU 시뮬레이션에서만 동작한다는 제약 말고도 비용을 따져 봐야 합니다. Scalability and Best Practices 문서는 파티클 속성 리더(Particle Attribute Reader) 데이터 인터페이스로 입자를 읽는 방식이 대체로 이벤트보다 빠르고, 대개 같은 동작을 만들 수 있다고 설명합니다. 그래서 이벤트 핸들러로 만든 효과가 무겁다면, 받는 이미터가 원본 이미터의 입자 속성을 직접 읽는 구성으로 바꿀 수 있는지 비교해 봅니다.
이벤트를 그대로 쓴다면 이미터 속성의 Combine Event Spawn도 알아 둘 만합니다. Emitter Properties 문서에 따르면 이 설정은 이벤트에 따른 생성을 한 번의 생성으로 합칩니다. 한 프레임에 소멸 이벤트가 많이 몰리는 효과라면, 받는 이미터에서 이 설정을 켰을 때와 껐을 때의 모양과 비용을 같은 조건에서 비교합니다.
정리
- 이벤트 핸들러는 한 이미터에서 생긴 소멸이나 충돌 같은 이벤트를 같은 시스템의 다른 이미터가 받아 동작하게 하며, CPU 시뮬레이션에서만 씁니다.
- 원본 이미터에는
Requires Persistent IDs를 켜고 Particle Update에Generate Death Event같은 발생 모듈을 둡니다. - 받는 이미터에는 Event Handler 그룹을 더해
Source로 실제 발생기의 이벤트를 고르고,Receive Death Event같은 모듈로 데이터를 받습니다. - 받는 이미터는 자체 생성 모듈을 끄고, 이벤트를 기다리는 동안 켜져 있어야 합니다.
- 새 입자 수는 처리된 이벤트 수에
Spawn Number를 곱한 값이며,Max Events Per Frame을 넘는 이벤트는 무시됩니다.
연습 문제
1. 처리 한도를 넘는 이벤트
한 프레임에 이벤트 9개가 생기고, Max Events Per Frame은 4, Spawn Number는 2, Random Spawn Number는 꺼져 있습니다. 받는 이미터는 켜져 있고 다른 생성 모듈은 없으며, 그 프레임에 만든 입자를 모두 유지합니다. 처리한 이벤트와 무시한 이벤트, 새로 만든 입자는 각각 몇 개일까요?
해설 보기
처리한 이벤트는 한도인 4개이고, 넘친 5개는 무시됩니다. 새 입자는 처리한 이벤트 수에 이벤트당 수량을 곱해 4 × 2 = 8개입니다.
생긴 9개를 모두 처리했다고 보고 18개로 계산하거나, 넘친 이벤트가 다음 프레임으로 자동으로 미뤄진다고 판단하면 안 됩니다. 이후에 살아 있는 수는 새 입자들의 수명과 Kill 조건을 따로 적용해 구합니다.
2. 원점에서만 터지는 폭발
연결을 마친 뒤 재생해 보니, 원본 입자가 사라지는 자리가 아니라 이미터의 원점에서 주기적으로 폭발 입자가 터집니다. 무엇을 확인해야 할까요?
해설 보기
BurstOnDeath에 템플릿의 Spawn Burst Instantaneous나 Spawn Rate가 남아 있는지 확인합니다. 이 모듈이 켜져 있으면 이벤트와 상관없이 이미터가 스스로 입자를 만들고, 그 입자는 이벤트의 위치를 받지 않으므로 원점에서 생깁니다.
이 모듈을 지우거나 끈 뒤에도 사라지는 자리에 입자가 생기지 않는다면, Event Handler 그룹에 Receive Death Event가 있는지와 두 이미터의 좌표 공간이 맞는지 확인합니다.
3. GPU로 바꾸자 사라진 반응
원본 이미터의 입자가 많아져서 Sim Target을 GPU로 바꿨더니, 폭발 입자가 더 이상 생기지 않습니다. 이유는 무엇이고 어떻게 해야 할까요?
해설 보기
나이아가라의 이벤트는 현재 GPU 시뮬레이션에서 동작하지 않고 CPU 시뮬레이션에서만 쓸 수 있습니다. 그래서 원본을 GPU로 바꾸면 Death 이벤트가 만들어지지 않아 받는 이미터가 반응하지 않습니다.
이벤트 연결을 유지하려면 원본을 CPU 시뮬레이션으로 되돌리고 입자 수를 다른 방법으로 줄입니다. GPU 시뮬레이션이 꼭 필요하다면 이벤트 핸들러가 아닌 다른 데이터 전달 방식을 따로 설계해야 합니다.
이벤트 핸들러의 Source와 Execution Mode, 처리 한도는 Epic의 Event Handler 그룹 레퍼런스에서 확인할 수 있습니다.
다음 글 기본 파티클 렌더링 설정에서는 렌더러의 머티리얼과 정렬, 바인딩 같은 설정을 다듬어 입자가 의도한 모습으로 보이게 하는 방법을 살펴봅니다.