언리얼 엔진의 나이아가라(Niagara) 시스템은 기본 기능만으로도 다양한 이펙트를 제작할 수 있다. 하지만 게임을 개발하다 보면 단순한 파티클 설정만으로는 표현하기 어려운 상황이 종종 발생한다.
이를 위해 나이아가라는 모듈(Module) 이라는 기능을 제공한다. 모듈은 블루프린트와 유사한 방식으로 동작하며, 파티클의 생성 및 동작 로직을 직접 작성할 수 있게 해준다.
예를 들어 아래와 같은 투사체 트레일(Trail) 이펙트를 생각해 보자.

일반적으로 투사체가 적이나 지형에 충돌하면 투사체 액터와 함께 나이아가라 컴포넌트도 제거된다. 그런데 이 경우 트레일이 자연스럽게 끝나는 것이 아니라 중간에서 갑자기 잘려 보이는 문제가 발생할 수 있다.
물론 충돌 시점에 별도의 나이아가라 시스템을 생성하는 방식으로도 해결할 수도 있고, 나이아가라 시스템을 추가로 시뮬레이션하거나 사라지는 타이밍을 한 프레임 미루는 등 다른 방법으로 처리할 수도 있다. 하지만 경우에 따라서는 나이아가라 내부에서 직접 처리하는 편이 더 자연스러울 수 있다.
예를 들어 충돌 직전의 위치와 최종 적중 지점을 이용하여 추가 파티클을 생성하면, 트레일이 적중 지점까지 이어지는 것처럼 표현할 수 있다. 이러한 종류의 로직은 나이아가라 모듈을 활용하면 비교적 깔끔하게 구현할 수 있다.
로컬 모듈 생성하기
나이아가라에서는 블루프린트와 유사한 형태로 로직을 작성할 수 있는 로컬 모듈(Local Module)을 제공한다.

나이아가라 시스템 에디터에서 원하는 스택 위치의 + 버튼을 누른 뒤 New Scratch Pad Module을 선택하면 새로운 모듈을 생성할 수 있다.
생성된 모듈은 블루프린트 그래프와 비슷한 형태의 에디터를 제공하며, 여기에서 파티클의 생성 및 동작 로직을 직접 작성할 수 있다.
이번 예제에서는 외부에서 값을 받아 특정 상황에서만 추가 파티클을 생성할 수 있도록 Input 변수를 만들어 보겠다.
Input 변수 만들기
나이아가라에서는 로컬 모듈(Local Module)을 통해 블루프린트와 유사한 방식으로 이펙트 로직을 작성할 수 있다.
하지만 이펙트의 동작을 외부 상황에 따라 변경하려면 값이 필요하다. 이를 위해 로컬 모듈은 Input 형태의 변수를 제공한다.

모듈 그래프에서 Map Get 노드의 + 버튼을 눌러 새로운 입력 변수를 추가할 수 있다.
생성된 변수는 모듈 내부에서 자유롭게 사용할 수 있으며, 이를 활용해 원하는 이펙트 동작을 구현할 수 있다.

다만 Input 변수는 자동으로 값이 채워지지 않는다. 따라서 외부에서 값을 주입해주어야 한다.
User Parameter와 연결하기
모듈을 저장하고 Apply한 뒤 System Overview로 돌아가면 생성한 로컬 모듈을 확인할 수 있다.
해당 모듈을 선택하면 우측 Details 패널에 모듈 내부에서 정의한 Input 변수들이 표시된다.

각 변수 우측의 ▼ 버튼을 누르면 값 할당 방식을 선택할 수 있는데, 여기서 Read from New User Parameter 를 선택하면 해당 Input 변수를 User Parameter와 연결할 수 있다.

User Parameter는 나이아가라 시스템이 제공하는 외부 노출 변수이며, 블루프린트나 C++ 코드에서 값을 변경할 수 있다.
예를 들어 Input 변수 Input.bSpawnEndpoint를 User Parameter로 승격하면 외부에서는 다음과 같이 접근할 수 있다.
NiagaraComponent->SetVariableBool(TEXT("User.bSpawnEndpoint"), true);
이렇게 잘 할당해서 처리하면, 아래와 같이 파티클을 내가 원하는 대로 편집하는 것이 가능해진다.

User Parameter 존재 여부 확인하기
나이아가라는 SetVariableBool() 호출 시 해당 변수가 실제 존재하는지 직접 확인하는 메서드를 제공하지 않는다. 반환 값이 따로 없어서 실제로 값이 할당되었는지 확인할 수도 없다.
대신 UNiagaraSystem::GetExposedParameters()를 이용한다면 노출된 User Parameter 목록을 조회할 수 있다.
const FNiagaraUserRedirectionParameterStore& Params =
NiagaraSystem->GetExposedParameters();
FNiagaraVariable Var(
FNiagaraTypeDefinition::GetBoolDef(),
TEXT("bSpawnEndpoint"));
bool bExists = Params.IndexOf(Var) != INDEX_NONE;
이름 비교 실험
이때 이름이 얼마나 똑같아야 User Parameter가 인식되는지 궁금해져서 실험해보기로 했다.
변수명 bSpawnEndpoint에 대해 bSpawnEndpoint를 그대로 쓰는 버전, User 태그를 붙여서 User.bSpawnEndpoint로 검사하는 방법, 아에 다른 태그를 붙여서 Input.bSpawnEndpoint로 검사하는 방법까지 나누어서 실험해 보았다.
const FNiagaraUserRedirectionParameterStore& Params =
TracerSystem->GetExposedParameters();
FNiagaraVariable Var1(
FNiagaraTypeDefinition::GetBoolDef(),
TEXT("bSpawnEndpoint"));
FNiagaraVariable Var2(
FNiagaraTypeDefinition::GetBoolDef(),
TEXT("User.bSpawnEndpoint"));
FNiagaraVariable Var3(
FNiagaraTypeDefinition::GetBoolDef(),
TEXT("Input.bSpawnEndpoint"));
bool bExists1 = Params.IndexOf(Var1) != INDEX_NONE; // 결과: true
bool bExists2 = Params.IndexOf(Var2) != INDEX_NONE; // 결과: true
bool bExists3 = Params.IndexOf(Var3) != INDEX_NONE; // 결과: false

실험 결과 bSpawnEndpoint와 User.bSpawnEndpoint는 동일한 변수로 인식되었다.
이는 내부적으로 FName 기반 비교를 수행하기 때문으로 보인다. 또한 대소문자를 변경해도 동일한 결과를 얻을 수 있었다.
반면, 존재하지 않는 다른 태그(Input.bSpawnEndpoint)를 붙인 경우에는 정상적으로 인식되지 않았다.
즉 User Parameter 조회 시에는 bSpawnEndpoint 또는 User.bSpawnEndpoint를 사용해도 동일하게 동작하지만, 임의의 접두어를 붙인 이름은 별개의 변수로 처리된다는 점을 확인할 수 있었다.
'Unreal Engine 5' 카테고리의 다른 글
| 언리얼 엔진5 - 충돌 이벤트 처리 (0) | 2026.06.06 |
|---|---|
| 언리얼 엔진 - 전방 선언하고 include 안 할 때를 주의하자(error C2440: 'static_cast' : cannot convert from ...) (0) | 2026.05.31 |
| 퍼포스와 Visual Studio를 같이 사용하는 방법 (0) | 2026.04.16 |
| 오라클 프리티어 기반 Perforce 설정하기 2 - 인스턴스에 퍼포스 연결하기 (0) | 2026.03.29 |
| 오라클 프리티어 기반 Perforce 설정하기 1 - 오라클 클라우드 생성하기 (0) | 2026.03.29 |
댓글