3D Video Production/Unreal Engine (5.6.1)

UE 5.6 Particle: Event Handler를 활용한 Niagara 제작

보별 2026. 10. 2. 16:43
반응형

이번 포스트에서는 언리얼 엔진의 Niagara 기본 Template을 활용해 여러 종류의 Particle Effect를 제작하고, 이후에는 Emitter끼리 Event를 주고받는 구조를 이용해 분수와 불꽃놀이처럼 여러 단계로 이어지는 효과를 제작했다.

지난 포스트에서 Niagara의 기본적인 Module과 Particle 수정 방법을 익혔다면, 이번에는 한 단계 더 나아가 Location Event, Collision Event, Death Event를 이용해 각각의 Emitter가 서로 연결되는 구조를 확인했다.

또한 Sprite Renderer뿐 아니라 Mesh Renderer, Ribbon Renderer, Light Renderer까지 사용하면서 Particle의 시뮬레이션과 실제 화면에 표현되는 방식이 서로 분리되어 있다는 점도 확인했다.

 

Niagara System & Emitter 구분하기

Niagara를 생성할 때 가장 먼저 보게 되는 것이 Template 선택 창이다.

첨부한 이미지처럼 이 창에서는 여러 기본 Template이 카드 형태로 정리되어 있고, 카드 하단의 색과 항목 이름 아래 표기된 자산 종류를 통해 Niagara Emitter인지 Niagara System인지 구분할 수 있다.

위 이미지를 보면 주황색 하단선이 있는 항목들은 Niagara Emitter, 하늘색 하단선이 있는 항목들은 Niagara System으로 표시되어 있다.

예를 들어 BlowingParticles, ConfettiBurst, Fountain 같은 항목은 Emitter로 표시되고, DirectionalBurst Lightweight, Fountain Lightweight, Minimal Lightweight, NS_ClonerBase, NS_EffectorBase 같은 항목은 System으로 표시된다.

이 차이를 간단하게 정리하면, Emitter는 개별 효과를 만들어내는 하나의 발생 단위이고, System은 하나 이상의 Emitter를 묶어 하나의 완성된 VFX로 구성한 상위 구조라고 볼 수 있다.
즉 Emitter는 효과를 이루는 부품에 가깝고, System은 그 부품들을 조합한 결과물에 가깝다.

예를 들어 불꽃놀이를 만든다고 하면, 한 Emitter는 불꽃을 위로 발사하고, 다른 Emitter는 꼬리를 만들고, 또 다른 Emitter는 마지막 폭발을 담당할 수 있다.
이처럼 여러 Emitter를 묶어 하나의 효과로 관리하는 것이 Niagara System이다.

또한 이 창의 왼쪽 아래에는 Create Empty Niagara System 버튼도 있어, Template를 사용하지 않고 처음부터 비어 있는 System을 만들어 직접 구성할 수도 있다.

다만 초반에는 원하는 효과와 비슷한 Template을 출발점으로 삼는 편이 훨씬 빠르고 구조를 이해하기도 쉽다.

이번 작업에서도 이런 기본 Template들을 바탕으로 환경 Particle과 Event 기반 효과를 순차적으로 제작했다.

 

Blowing Particles로 바람에 날리는 나뭇잎 만들기

나뭇잎 Static Mesh 준비

먼저 Blowing Particles Template을 선택해 Niagara System을 생성했다.

Blowing Particles는 기본적으로 바람에 영향을 받으며 Particle이 흩날리는 형태이기 때문에 나뭇잎이나 꽃잎처럼 가벼운 물체가 공중에서 움직이는 효과를 제작하기 좋은 출발점이다.

다음으로 Particle로 사용할 나뭇잎 Static Mesh를 준비했다.

다만 Mesh Particle은 Sprite와 달리 실제 Geometry를 반복해서 렌더링하기 때문에 지나치게 복잡한 Mesh를 그대로 사용하는 것은 좋지 않다.

위 이미지에서는 나뭇잎 내부에 굉장히 많은 삼각형이 생성되어 있는 것을 확인할 수 있다.

이 정도의 세분화는 가까이에서 단독으로 보여주는 모델이라면 문제가 되지 않을 수 있지만, 하나의 Niagara System에서 수십~수백 개씩 반복해서 생성할 Mesh라면 불필요한 비용이 될 수 있다.

따라서 Modeling Mode - Mesh - Simplify를 이용해 나뭇잎의 외곽 형태와 텍스처가 크게 깨지지 않는 범위에서 Triangle 수를 줄였다.

이 작업에서는 숫자를 무조건 낮추는 것보다 실제로 화면에서 차이가 느껴지는 지점까지 낮춘 뒤 한 단계 되돌아가는 방식이 안전하다.

Simplify 비율을 지나치게 낮추면 우측 이미지와 같이 텍스처가 깨져보일 수 있음

나뭇잎 Mesh의 Pivot도 확인했다.

Modeling Mode - XForm - Edit Pivot에서 Pivot을 Mesh의 가운데로 이동했다.

바람에 나뭇잎이 회전하는 효과에서는 Pivot이 한쪽으로 치우쳐 있으면 나뭇잎 자체가 회전하는 것이 아니라 큰 원을 그리며 빙빙 도는 것처럼 보일 수 있다.

따라서 특별한 연출 목적이 없다면 나뭇잎 중심 근처에 Pivot을 배치하는 것이 자연스럽다.

기존 Sprite Renderer를 비활성화한 뒤 Mesh Renderer를 추가했다.

이번 작업에서는 Renderer를 추가한 뒤 표시되는 경고를 Fix Issue로 해결하고, Particle Mesh에 앞서 준비한 나뭇잎 Static Mesh를 지정했다.

Mesh 크기에 Random 적용

Initialize Particle - Mesh Attributes에서 Mesh Scale Mode를 Random Uniform으로 설정하고 최소·최대 크기를 조절했다.

Random Uniform은 각 Particle마다 다른 크기를 지정하지만 X·Y·Z에 같은 배율을 적용하기 때문에 Mesh의 원래 비율은 유지된다.

모든 나뭇잎이 같은 크기로 생성되는 것보다 작은 잎과 큰 잎이 섞여 있는 편이 훨씬 자연스럽게 보인다.

Manny를 이용해 실제 크기 확인

레벨에 Manny를 배치한 뒤 실제 캐릭터와 나뭇잎의 크기를 비교했다.

Niagara Editor의 Preview만 보고 Particle 크기를 설정하면 실제 레벨에 배치했을 때 생각보다 지나치게 크거나 작게 느껴지는 경우가 있기 때문이다.

이미지를 보면 캐릭터 주변부터 지면까지 여러 크기의 나뭇잎이 흩어져 있어 Random Uniform이 적용된 결과도 확인할 수 있다.

이처럼 사람이나 문, 차량처럼 크기를 직관적으로 알고 있는 오브젝트를 기준으로 VFX 크기를 잡으면 스케일 오류를 훨씬 빨리 발견할 수 있다.

Collision 조절

나뭇잎이 지면에 닿았을 때 자연스럽게 멈추도록 Collision도 수정했다.

Particle Radius Scale은 Collision 판정에 사용하는 Particle 반경에 영향을 준다.

값이 지나치게 작으면 Mesh 일부가 바닥 아래로 들어간 것처럼 보일 수 있고, 반대로 너무 크게 설정하면 Mesh가 실제 바닥에 닿기도 전에 떠 있는 것처럼 충돌할 수 있다.

따라서 Mesh가 지면을 크게 관통하지 않으면서 떠 보이지 않는 값을 찾는 것이 중요하다.

Friction 값도 높였다.

Friction이 커지면 지면과 충돌한 Particle이 표면을 따라 계속 미끄러지는 움직임이 줄어들기 때문에, 떨어진 나뭇잎이 바닥에 정착하는 느낌을 만들기 쉽다.

그림자 & 바람 조절

레벨에 배치한 Niagara System Actor를 선택한 뒤 Details의 Rendering 항목에서 Cast Shadow를 활성화해 나뭇잎이 주변 바닥과 오브젝트에 그림자를 만들도록 했다.

다만 Particle 수가 많을 때는 Shadow 또한 비용이 되므로 화면에서 실제로 필요한지 판단해서 사용하는 것이 좋다.

이후 필요에 따라 Spawn Rate, Gravity Force, Wind Force, Aerodynamic Drag 등을 조절했다.

Gravity Force는 아래로 떨어지는 힘을 만들고, Wind Force는 전체적인 이동 방향을 만든다.

Aerodynamic Drag는 공기저항과 관련된 움직임을 만들어 나뭇잎처럼 가벼운 Mesh가 바람을 따라 움직이는 느낌을 조절할 때 사용할 수 있다.

나뭇잎은 단순히 이동 속도만 높이는 것보다 중력·바람·저항이 서로 다른 방향으로 작용할 때 훨씬 자연스럽게 보였다.

 

Confetti Burst로 축하 효과 만들기

다음은 Confetti Burst Template을 이용해 생일 축하나 파티에서 사용하는 색종이 효과를 제작했다.

Confetti Burst는 시작과 동시에 여러 Particle을 넓게 터뜨리는 움직임이 이미 구성되어 있다.

따라서 기본적인 움직임을 다시 만들기보다는 Renderer의 Material을 원하는 이미지나 색종이 Material로 교체하는 방식으로 빠르게 활용할 수 있다.

Sprite Renderer - Material을 변경하면 Particle의 실제 화면 표현을 바꿀 수 있다.

얇은 종이나 카드처럼 회전하면서 앞·뒷면이 모두 보여야 하는 Material이라면 Two Sided 옵션도 확인한다.

Two Sided Material은 뒷면도 렌더링하므로 회전 중 특정 각도에서 Particle이 사라지는 현상을 줄일 수 있다.

 

Hanging Particulates로 공기 중 먼지 표현하기

다음은 Hanging Particulates Template을 이용했다.

Hanging Particulates는 공기 중에 천천히 떠다니는 작은 Particle을 만들기 때문에 먼지, 부유물, 실내 공기 속 미세 입자 등을 표현할 때 사용하기 좋다.

먼지 효과에서 특히 중요한 것은 Particle의 크기다.

먼지가 너무 크거나 밝으면 관객의 시선이 배경이나 캐릭터가 아니라 Particle 자체에 집중된다.

따라서 먼지는 보이지 않는 것이 아니라, 의식하지 않을 정도로 보이는 것을 목표로 하는 편이 좋다.

이번 작업에서는 먼저 Scale Sprite Size, Scale Color 등을 비활성화하고 Initialize Particle에서 기본적인 Sprite Size를 직접 조절했다.

Template에 들어 있는 시간 변화 효과를 잠시 제거하면 어떤 값이 기본 크기에 영향을 주는지 확인하기 쉽기 때문이다.

기본 크기를 잡은 뒤 필요하면 Scale 모듈을 다시 이용해 수명에 따른 변화를 추가할 수 있다.

실제 환경 VFX에서는 이런 작은 Particle 하나가 눈에 띄기 시작하는 순간 효과가 과해졌다고 판단하기 쉬웠다.

 

Recycle Particles In View로 눈 내리는 효과 만들기

다음은 Recycle Particles In View Template을 사용해 눈이 내리는 효과를 제작했다.

이 Template은 카메라 주변에서 반복적으로 Particle을 보여주는 눈이나 꽃잎 같은 환경 효과의 출발점으로 사용할 수 있다.

Spawn Burst Instantaneous에서 Burst Count를 조절해 화면에 존재하는 Particle 양을 맞추고, Initialize Particle에서 눈의 기본 크기를 수정했다.

카메라에 가까운 Particle은 크게 보이고 멀리 있는 Particle은 작게 보이기 때문에, 실제로 레벨에서 카메라를 움직이며 밀도를 확인하는 것이 중요하다.

이런 환경 Particle은 Particle 하나의 완성도보다 화면 전체에서 느껴지는 밀도와 깊이감이 더 중요하게 느껴졌다.

 

Niagara Event 이해하기

이번 포스트에서 가장 중요한 부분이 Niagara의 Event다.

Event는 간단하게 말하면 Emitter A에서 발생한 정보를 Emitter B가 받아 새로운 Particle이나 동작을 만드는 기능이다.

Location Event는 소스 Particle의 위치 정보를 전달한다.

예를 들어 위로 날아가는 불꽃의 위치를 계속 전달하면 다른 Emitter가 그 위치에 Particle을 만들어 불꽃을 따라오는 Trail을 만들 수 있다.

Death Event는 소스 Particle의 수명이 끝나 사라지는 순간 발생한다.

따라서 불꽃 발사 후 Lifetime 종료 시 폭발과 같은 구조에 사용할 수 있다.

Collision Event는 Particle이 바닥이나 Static Mesh 등의 Collision과 충돌했을 때 Event를 발생시킨다.

예를 들어 분수에서 물방울이 바닥에 닿는 순간 작은 물방울을 추가로 생성하는 데 사용할 수 있다.

Event를 사용할 때 필요한 설정

현재 언리얼 엔진 5.6의 Niagara Event는 GPU Simulation이 아니라 CPU Simulation에서만 동작한다.

또 Event를 생성하는 Emitter에서는 Emitter Properties의 Requires Persistent IDs를 활성화해야 한다.

Persistent ID는 Particle에 수명 동안 유지되는 식별자를 부여해 Event처럼 Particle을 지속적으로 추적하는 기능에서 사용할 수 있도록 한다.

이 부분은 단순한 옵션 하나가 아니라 이후 Event 시스템 전체가 동작하기 위한 전제 조건이므로 반드시 확인해야 한다.

 

Collision Event를 이용한 분수 만들기

이번에는 Fountain Template을 이용해 하나의 Particle이 바닥과 충돌하면 다른 Emitter가 반응하는 효과를 제작했다.

Fountain System 생성

먼저 Fountain Template으로 새로운 Niagara System을 생성했다.

기존 Fountain Emitter는 위쪽으로 Particle을 뿜어내는 역할을 한다.

여기에 Add Minimal Emitter를 이용해 아무 효과도 없는 새로운 Emitter를 추가했다.

Minimal Emitter는 필요한 Module만 직접 추가해서 만들 수 있기 때문에 Event를 받는 전용 Emitter를 제작할 때 유용하다.

Source Emitter에서 Collision Event 생성

기존 Fountain Emitter는 CPU Simulation을 유지하고 Emitter Properties의 Requires Persistent IDs를 활성화했다.

그 다음 Particle Update에 Generate Collision Event를 추가했다.

Niagara에서 필요한 Module Dependency가 빠져 있는 경우 경고가 나타날 수 있으며, 이번 작업에서는 Fix Issue를 이용해 Collision 계산에 필요한 Module을 추가했다.

Collision Module은 실제 충돌을 계산하고, Generate Collision Event는 그 결과를 Event 데이터로 전달하는 역할을 한다.

Minimal Emitter에서 Event Handler 추가

Minimal Emitter에서 Stage를 눌러 Event Handler를 추가했다.

Event Handler Properties의 Source에는 Emitter: Fountain / Event: Collision을 지정했다.

즉 Fountain Emitter에서 발생한 Collision Event만 받도록 설정한 것이다.

Execution Mode는 Spawned Particles로 변경하고, Spawn Number는 7로 설정했다.

Spawned Particles는 해당 Event에 반응해 새로 생성된 Particle에 Event Script를 실행하는 모드다.

따라서 하나의 Collision Event가 처리될 때 여러 개의 작은 Particle이 발생하게 된다.

Receive Collision Event 추가

Event Handler 내부에 Receive Collision Event를 추가했다.

이제 Fountain의 Particle이 바닥에 충돌한 위치를 받아 새로운 Particle을 생성할 수 있다.

이미지를 보면 큰 Fountain Particle이 바닥 부근에서 충돌한 뒤 그 주변으로 큰 Particle들이 퍼지는 것을 확인할 수 있다.

단일 Emitter에서는 단순히 물방울이 떨어지는 효과였지만 Collision Event를 연결하자 충돌한 위치에서 2차 Particle이 발생하는 구조가 만들어졌다.

Event를 실제 화면으로 확인하니 단순한 데이터 전달 기능이라기보다 하나의 효과가 다른 효과를 트리거하는 구조라는 점이 훨씬 명확했다.

Add Velocity로 충돌 Particle 튀기기

새 Particle이 바닥에 머무르지 않고 튀도록 Add Velocity를 추가했고, 필요한 Solver 관련 Module이 없다면 Fix Issue를 통해 추가할 수 있다.

생성되는 Particle의 크기를 줄여준 뒤, Velocity Mode를 In Cone으로 바꿔 바닥에서 위쪽으로 일정한 각도로 퍼지도록 했다.

모든 Particle이 같은 속도로 튀면 규칙적인 모양이 금방 보이기 때문에 Velocity Speed를 Random Range Float로 변경한 뒤 적당한 수치를 적용했다.

각 Particle마다 서로 다른 속도를 갖게 되어 한 번에 동일한 높이까지 올라가는 현상이 줄어든다.

Gravity Force 추가

위로 튀기기만 하면 Particle이 계속 상승하거나 부자연스럽게 떠 있는 느낌이 생긴다.

따라서 Gravity Force를 추가해 상승한 뒤에 감속하며 하강하는 과정을 만들었다.

이렇게 서로 다른 Emitter의 움직임이 한 화면에 나타나지만 실제 내부 구조는 Collision Event로 연결되어 있다.

Plane 아래로 떨어지는 Particle 제거

Plane 아래쪽에서 효과를 확인하면 일부 Particle이 Collision 이후 불필요하게 바닥 아래까지 내려가는 것을 볼 수 있었다.

Kill On Collision을 활성화하면 Collision이 발생한 Particle을 제거할 수 있다.

눈에 보이지 않는 지면 아래에서 Particle이 계속 존재할 이유가 없다면 이렇게 제거해 불필요한 시뮬레이션과 시각적 오류를 줄이는 것이 좋다.

 

Niagara Event로 불꽃놀이 만들기

이번 작업에서 가장 많은 내용을 조합한 건 불꽃놀이였다.

기본 구조는 다음과 같다.

Rocket Emitter → Location Event → Ribbon Trail → Location Event → 추가 Jet Particle → Death Event → 폭발 Particle

즉 하나의 Rocket Particle 데이터를 여러 Emitter가 서로 다른 목적으로 사용한다.

불꽃의 초기 발사 만들기

Fountain Template으로 새로운 Niagara System을 생성했다.

Emitter는 CPU Simulation을 유지하고 Requires Persistent IDs를 활성화했다.

Spawn Rate를 낮춰 불꽃이 지나치게 자주 발사되지 않도록 했다.

Initialize Particle의 Lifetime은 약 1~2초 범위로 설정해 불꽃이 위로 올라간 뒤 일정 시간 후 사라지도록 했다.

불꽃 색상 Random 적용

Initialize Particle의 Color Mode를 Random Hue/Saturation/Value로 변경했다.

Hue 범위를 넓게 설정하면 생성되는 Particle마다 서로 다른 색상 계열을 사용할 수 있다.

이번 설정에서는 Hue Range를 0~1로 설정해 다양한 Hue가 나타나도록 만들었다.

여기서 용어를 구분해두면 좋다.

Hue: 색상 종류
Saturation: 색의 선명도
Value: 색의 밝기

따라서 색을 강렬하게 보이게 하려면 단순히 Value만 높이는 것이 아니라 Saturation과 Value를 목적에 맞게 조절해야 한다.

Add Velocity로 높이 발사

Add Velocity의 값을 크게 설정해 Particle이 빠르게 위쪽으로 발사되도록 했다.

이 상태에서는 일정한 속도로 계속 올라가는 느낌이 강하기 때문에 Drag를 추가했다.

결과적으로 아래와 같은 움직임을 만들 수 있다.

빠르게 발사 → 점차 감속 → 최고점 접근

Location Event & Death Event 생성

Rocket Emitter에는 두 종류의 Event를 생성했다.

Generate Location Event는 불꽃이 이동하는 동안 현재 위치를 전달하고, Generate Death Event는 Lifetime이 끝나 Rocket Particle이 사라지는 순간 Event를 발생시킨다.

앞으로 Location Event는 불꽃의 꼬리에, Death Event는 마지막 폭발에 사용한다.

Ribbon으로 불꽃의 꼬리 만들기

새로운 Minimal Emitter를 추가하고, Stage에서 Event Handler를 생성한 뒤 Receive Location Event를 추가했다.

Source에는 Rocket Emitter의 Location Event를 지정하고, Execution Mode는 Spawned Particles로, Spawn Number는 1로 설정했다.

즉 Rocket Particle이 이동하며 전달하는 위치 데이터를 따라 Particle이 하나씩 생성된다.

Sprite Renderer를 Ribbon Renderer로 변경

기존 Sprite Renderer를 비활성화하고 Ribbon Renderer를 추가했다.

Ribbon Renderer는 여러 Particle을 선 형태로 이어 Trail을 만든다.

불꽃의 꼬리가 지나치게 오래 남으면 긴 선처럼 보이므로 Initialize Particle의 Lifetime을 짧게 설정했다.

Initialize Particle의 Ribbon Attributes에서 Ribbon Width를 Direct Set으로 변경하고 Ribbon의 두께를 설정했다.

이 값은 Trail의 전체 인상을 크게 바꾸므로 최종 카메라 거리에서 확인하는 것이 좋다.

Rocket Emitter의 색상 전달하기

초기 상태에서는 위 이미지와 같이 Trail이 흰색으로 나타났다.

Rocket Emitter에서 위치만 전달하고 색상 정보는 적용하지 않았기 때문이다.

Receive Location Event의 Color를 Apply로 변경했다.

RGB와 Alpha 정보가 적용되면서 Rocket Particle의 색상을 Trail도 그대로 따라갈 수 있게 된다.

Location Event를 단순 위치 정보라고 생각하기 쉽지만 Receive Module을 통해 Color나 Velocity 등 필요한 Event Data도 선택적으로 적용할 수 있다는 것이 중요한 부분이다.

Curl Noise Force로 직선 느낌 줄이기

Ribbon이 지나치게 매끄러운 직선으로만 이어지면 인위적으로 보일 수 있다.

따라서 Curl Noise Force를 추가해 Trail이 약간씩 흔들리고 휘어지는 느낌을 만들었다.

여기서 Noise 값을 너무 크게 올리면 불꽃의 진행 방향보다 흔들림이 더 강해질 수 있으므로 기본적인 Rocket 진행 형태가 유지되는 선에서 사용하는 것이 좋다.

불꽃 뒤쪽의 추가 Jet Particle 만들기

Ribbon 외에도 불꽃의 움직임을 풍부하게 만들어줄 추가 Minimal Emitter를 생성했다.

이 Emitter 역시 Rocket의 위치를 따라가야 하므로 Receive Location Event를 사용한다.

Non-Uniform Sprite Size 사용

Initialize Particle의 Sprite Size Mode를 Non-Uniform으로 설정했다.

Uniform은 가로·세로 크기를 같은 비율로 설정하지만 Non-Uniform은 X와 Y 크기를 각각 독립적으로 조절할 수 있어서, 10 × 100처럼 길쭉한 Sprite를 사용할 수 있다.

불꽃의 작은 점이 아니라 진행 방향으로 길게 뻗는 Spark를 만들 때 적합하다.

Velocity Aligned 설정

처음에는 길쭉한 Sprite가 실제 진행 방향과 관계없이 일정한 방향으로 생성됐다.

Sprite Renderer의 Alignment를 Velocity Aligned로 변경했다.

Velocity Aligned는 Sprite의 기준 축이 Particles.Velocity 방향을 따라가도록 하기에, 긴 Sprite를 불꽃의 이동 방향과 나란히 배치할 수 있다.

Location Event의 Velocity 적용

하지만 Alignment를 Velocity Aligned로 바꾸는 것만으로는 충분하지 않다.

Target Emitter가 Rocket의 Velocity 정보를 사용하려면 Receive Location Event의 Velocity 역시 Apply로 설정한다.

이미지에서는 Inherited가 0.5로 설정되어 있다.

즉 원본 Particle의 Velocity를 일정 비율만큼 물려받아 움직인다.

Velocity Aligned는 방향을 결정할 데이터를 필요로 하고, Receive Location Event는 그 데이터를 전달하는 역할을 하는 셈이다.

From Point로 방사형 움직임 추가

추가 Particle이 Rocket 진행 방향을 그대로 복사하기만 하면 너무 일정한 직선이 된다.

Add Velocity를 추가하고 Velocity Mode를 From Point로 설정했다.

From Point는 특정 점에서 바깥쪽으로 향하는 방향을 만들어주기 때문에 Rocket 주변으로 Particle이 퍼지는 느낌을 추가할 수 있다.

Inherited Velocity를 음수 범위로 설정

Receive Location Event의 Velocity - Inherited를 Random Range Float로 변경하고, 약 -0.7 ~ -0.4 범위를 지정했다.

음수 계수를 사용하면 전달받은 Rocket Velocity의 반대 방향 성분이 생긴다.

따라서 Rocket이 위로 이동한다면 작은 Spark는 상대적으로 뒤쪽으로 흩어져 불꽃 뒤에 남는 Jet Effect처럼 보이게 된다.

또 값을 Random Range로 사용했기 때문에 모든 Spark가 완전히 같은 속도로 뒤로 이동하지 않는다.

수명에 따라 작아지도록 설정

Scale Sprite Size를 추가해 Particle의 Lifetime 후반으로 갈수록 크기가 0에 가까워지도록 Curve를 설정했다.

이는 Alpha Fade와는 조금 다르다.

Sprite 자체의 크기가 줄어들기 때문에 화면에서는 점점 작아지며 사라지는 느낌을 만든다.

Ribbon에는 같은 방식으로 Scale Ribbon Width를 적용해 불꽃의 꼬리가 끝부분으로 갈수록 얇아지도록 했다.

Death Event로 불꽃 폭발 만들기

마지막으로 Rocket이 수명을 다했을 때 터지는 불꽃을 제작했다.

Minimal Emitter를 하나 더 추가하고 Event Handler에서 Receive Death Event를 사용했다.

Source는 Rocket Emitter의 Death Event로 설정하고, 색상을 이어받도록 Color를 Apply로 바꿨다.

즉 Rocket Particle이 사라지는 순간 새로운 Particle이 생성된다.

From Point로 폭발시키기

Add Velocity를 추가하고 From Point를 사용해 Particle을 중심에서 바깥쪽으로 퍼뜨렸다.

Velocity Speed를 높이면 폭발 직후 빠르게 확산된다.

하지만 계속 같은 속도로 움직이면 지나치게 멀리 퍼지므로 Drag도 추가했다.

Particle 형태 조절

Initialize Particle에서 Lifetime과 Non-Uniform Sprite Size를 조절했다.

Sprite Renderer의 Alignment는 Velocity Aligned로 설정해 길쭉한 Particle이 폭발 방향을 따라 향하도록 했다.

Scale Sprite Size & Scale Color

Particle이 끝까지 같은 크기와 밝기를 유지하면 갑자기 사라지는 느낌이 나기 쉽다.

따라서 Scale Sprite Size Curve를 이용해 수명 후반부에 크기를 줄였다.

Scale Color에서는 RGB 값을 높여 불꽃이 밝고 강하게 보이도록 하고, Scale Alpha의 Curve for Floats도 이용해 Lifetime이 끝날수록 Alpha가 감소하도록 했다.

이때 RGB 값을 높이는 것은 Particle의 물리적인 폭발 힘을 높이는 것이 아니라 색상 또는 Emissive 표현을 더 밝게 만드는 것이다.

결과적으로 아래와 같은 형태를 만들 수 있다.

강하게 발광 → 점점 어두워짐 → 사라짐

마지막으로 Gravity Force를 추가해 폭발 이후 Particle들이 서서히 아래쪽으로 떨어지도록 했다.

최종 불꽃놀이 확인

최종 화면에서는 여러 색상의 불꽃이 서로 다른 위치에서 폭발하며 각 Emitter들이 하나의 효과처럼 연결되는 것을 확인할 수 있다.

밝은 낮 환경에서는 Emissive와 색상 차이를 확인하기 어렵기 때문에 테스트할 때는 주변 환경을 어둡게 설정했다.

이후 실제 Level Design에 맞춰 불꽃 색상, 발사 간격, 발사 범위, 폭발 크기, Particle 수 등을 조절하면 된다.

이번 작업은 Niagara의 Event 구조를 이해하고 나니 복잡해 보이는 불꽃놀이도 결국 몇 개의 단순한 Emitter가 순서대로 반응하는 구조라는 점이 가장 크게 느껴졌다.

 

Light Renderer

마지막으로 Fountain Template을 이용해 Renderer 종류를 추가로 확인했다.

Light Renderer를 추가하면 Particle 위치를 기준으로 Light를 생성할 수 있다.

Diffuse Scale 값을 조절하면 해당 Light가 주변 표면의 Diffuse Lighting에 미치는 영향을 조절할 수 있다.

여기서 주의해야 할 점은 Light Renderer 자체가 Sprite Material을 Emissive Material로 변경하는 것은 아니라는 것이다.

Light Renderer는 실제로 주변 Geometry를 비추는 Light를 생성하는 기능이기에, 많은 Particle에 Light Renderer를 적용하면 비용이 증가할 수 있으므로 필요한 Particle에 제한적으로 사용하는 편이 좋다.

 

Ribbon Renderer

같은 Niagara System에 Ribbon Renderer도 추가했다.

위 이미지를 보면 밝은 Particle을 따라 여러 개의 흰 Ribbon 궤적이 이어져 있는 걸 확인할 수 있다.

Ribbon Renderer는 Particle을 개별 점으로 보여주는 대신 서로 연결해 연속적인 선이나 띠 형태로 표현한다.

단순한 경우에는 Particle이 생성되는 순서를 따라 연결되는 것으로 이해해도 되지만, 정확하게는 같은 Ribbon을 구성하는 Particle들의 Ribbon ID와 연결 순서가 사용된다.
기본 Ribbon Renderer 구현도 Particle을 수명/연결 순서에 따라 잇는다.

따라서 불꽃 Trail, 검기, 에너지 궤적, 마법 Effect, 이동 잔상 등처럼 연속적인 경로가 필요한 VFX에 활용할 수 있다.

같은 Particle 데이터를 Sprite, Ribbon, Light처럼 서로 다른 Renderer가 각기 다른 방식으로 표현할 수 있다는 점을 확인하기 좋은 작업이었다.

 

이번 작업에서 기억할 Niagara 작업 순서

Niagara Effect를 만들 때는 바로 수치를 수정하기보다 다음 순서로 확인하면 정리가 쉽다.

  1. 원하는 움직임과 가까운 Template이 있는지 확인
  2. Particle이 Sprite인지 Mesh인지 결정
  3. Initialize Particle에서 크기·색상·Lifetime 등 초기값을 잡음
  4. Velocity로 기본적인 진행 방향을 만듦
  5. Gravity, Drag, Wind, Curl Noise 등으로 움직임을 다듬음
  6. Collision과 Event가 필요하다면 CPU/GPU Simulation 조건 확인
  7. Location·Collision·Death 중 어떤 데이터를 전달할지 결정
  8. Event Handler에서 Source, Execution Mode, Spawn Number, Receive Event 확인
  9. Scale Size·Scale Color 등을 이용해 Lifetime 끝부분을 자연스럽게 처리
  10. Particle 수, Mesh 복잡도, Shadow, Light Renderer 등의 성능 비용 확인

Niagara에서 효과가 이상하게 보일 때는 모든 Module 값을 한 번에 바꾸기보다 Spawn → 움직임 → Event → Renderer 순서로 원인을 좁혀가는 편이 훨씬 빠르다.

 

이번 작업에서는 Niagara의 기본 Template을 수정하는 단계에서 시작해, Collision·Location·Death Event로 여러 Emitter를 연결하고 Ribbon과 Light Renderer까지 활용하는 과정을 살펴봤다.

특히 불꽃놀이처럼 복잡해 보이는 Effect도 하나의 거대한 효과로 보기보다 각 Emitter의 역할과 서로 전달하는 데이터를 나누어 생각하면 구조를 훨씬 이해하기 쉬웠다.

앞으로 다른 Niagara Effect를 제작할 때도 Spawn → 움직임 → Event → Renderer 순서로 구조를 나누어 확인하면 원하는 결과를 만들거나 문제의 원인을 찾는 데 도움이 될 것 같다.