스크립트 최적화 기본 기법
불필요한 매 프레임 계산과 정밀도를 줄이고 CPU·GPU 실행, LOD·스케일러빌리티, 프로파일링으로 스크립트 비용을 관리합니다.
나이아가라는 매우 강력하고 유연한 파티클 시스템이지만, 그만큼 비효율적으로 사용될 경우 성능에 큰 부담을 줄 수 있습니다.
특히 복잡한 효과를 만들거나 많은 파티클을 사용할 때는 스크립트 최적화(Script Optimization)가 필수적입니다.
최적화는 단순히 빠르게 만드는 것을 넘어, 여러분의 효과가 다양한 하드웨어에서 정해진 프레임 시간 예산 안에서 작동하도록 조정하는 중요한 과정입니다.
이 절에서는 나이아가라 스크립트의 성능을 향상시키기 위한 몇 가지 기본적인 최적화 기법에 대해 알아보겠습니다.
왜 최적화해야 할까요?
나이아가라 시스템은 매 프레임마다 수천, 수만 개의 파티클에 대한 수백 가지의 계산을 수행할 수 있습니다.
각 계산이 아무리 사소해 보여도, 이들이 쌓이면 엄청난 연산량이 됩니다.
특히 다음과 같은 경우에 최적화의 필요성이 더욱 커집니다.
- 많은 파티클 수: 동시에 활성화되는 파티클 수가 많을수록 각 파티클에 대한 연산 부담이 커집니다.
- 복잡한 모듈 로직: 복잡한 수학 연산, 조건문, 데이터 인터페이스 호출 등이 많을수록 연산 시간이 늘어납니다.
- 성능 민감한 플랫폼: 모바일 기기, VR 등 사양이 제한적인 플랫폼에서는 작은 최적화로도 큰 성능 향상을 기대할 수 있습니다.
- 다수의 이펙트 동시 재생: 여러 나이아가라 효과가 한 화면에 동시에 재생될 때, 각각의 최적화가 전체 성능에 영향을 미칩니다.
불필요한 계산 피하기
가장 기본적인 최적화는 불필요한 일을 하지 않는 것입니다.
- 사용하지 않는 모듈 제거: 이미터에 추가되어 있지만 실제로는 아무런 기능도 하지 않거나, 더 이상 필요 없는 모듈은 과감하게 삭제하세요. 각 모듈은 나름의 연산 비용을 가집니다.
- 실제로 제거되는 계산 확인: Static Switch로 사용하지 않는 기능을 컴파일에서 제외하거나, 불필요한 모듈을 끕니다. 동적
Select/If만 붙여도 선택되지 않은 값의 계산이 생략된다고 가정하지 않습니다. - 불필요한 데이터 인터페이스 호출 자제: 데이터 인터페이스는 외부 데이터를 가져오는 데 비용이 발생합니다. 필요한 경우에만 호출하고, 같은 데이터를 여러 번 가져오기보다 한 번 가져와서 여러 곳에서 재사용하는 것이 좋습니다.
계산량 줄이기
같은 결과를 얻더라도 더 적은 연산으로 얻을 수 있는 방법을 찾아야 합니다.
- 수학 의미 보존: Lerp는 보간, Sine은 주기 함수입니다. 비용을 이유로 서로 바꾸면 움직임 자체가 달라질 수 있습니다. 근사가 허용되는 범위와 실제 비용을 비교합니다.
- 길이 비교: 거리 d가 0 이상인 임계값 R보다 작은지만 검사한다면
LengthSquared(v) < R × R로 제곱근을 피할 수 있습니다. 임계값도 제곱해야 하며, 방향이 필요할 때는 안전한 정규화를 사용합니다. - 반복 빈도: 변하지 않는 초기값은 Spawn에서 구하고, 모든 파티클에 공통인 값은 가능한 System/Emitter 단계에서 계산합니다. 상수나 반복된 Get은 컴파일러가 최적화할 수 있으므로 노드 개수만으로 비용을 단정하지 않습니다.
- 커브: 키를 정리하면 편집이 쉬워집니다. 런타임 비용은 키 개수뿐 아니라 커브 데이터 인터페이스의 LUT 베이킹과 샘플링 방식에 달려 있으므로 프로파일링으로 판단합니다.
GPU와 CPU 연산의 이해
나이아가라는 파티클 시뮬레이션을 CPU 또는 GPU에서 수행할 수 있습니다.
각 방식의 장단점을 이해하고 적절히 활용하는 것이 중요합니다.
-
GPU 시뮬레이션 활용
- 대규모 파티클 효과(수천, 수만 개)에는 GPU 시뮬레이션이 유리할 수 있습니다. 목표 하드웨어의 GPU 부하와 전송·디스패치 비용까지 비교합니다. GPU 이미터여도 System/Emitter 스크립트와 관리 비용은 CPU에 남습니다.
- 주의: GPU 시뮬레이션은 월드와의 충돌 처리, 블루프린트와의 양방향 통신 등 특정 CPU 기반 기능에 제약이 있을 수 있습니다. 모든 상황에 GPU 시뮬레이션이 최적은 아닙니다. 이미터의
Sim Target속성을GPU Compute로 설정하여 변경할 수 있습니다.
-
CPU 시뮬레이션 선택
- 정확한 충돌 처리, 복잡한 게임 로직과의 연동(블루프린트에서 파티클 데이터 읽기/쓰기), 적은 수의 파티클에는 CPU 시뮬레이션이 더 적합할 수 있습니다.
- 소규모 효과의 경우 CPU 시뮬레이션의 오버헤드가 크지 않으므로 굳이 GPU로 전환할 필요는 없습니다.
LOD (Level of Detail) 및 스케일러빌리티
Niagara Effect Type과 System/Emitter의 Scalability 설정에서 품질 단계, 거리·가시성 컬링, 인스턴스 예산, 생성량 배율을 설계합니다. 멀리 있다고 복잡한 효과가 자동으로 적절한 LOD로 바뀌는 것은 아닙니다.
- 거리별 생성량과 기능 축소를 명시하고 전환 시 실루엣과 타이밍이 유지되는지 확인합니다.
- Spawn Rate/Burst와 Lifetime을 함께 조절합니다. 메모리 할당 수를 지정하는 옵션을 살아 있는 파티클 수의 강제 상한으로 혼동하지 않습니다.
- Bounds가 너무 크면 컬링 효과가 줄고 너무 작으면 보이는 입자가 잘립니다.
- 유한 효과는 Emitter/System State의 루프와 Inactive Response를 맞춰 자연스럽게 완료되게 합니다. 컴포넌트의 Auto Destroy는 완료 후 컴포넌트 정리이며, 모든 입자가 없다는 이유만으로 계속 재생 중인 시스템을 완료시키는 설정은 아닙니다.
GPU 파티클 스케일러빌리티 주의사항
GPU 시뮬레이션은 강력하지만, 장면 전체에서 무분별하게 사용하면 오히려 프레임 드랍을 키울 수 있습니다.
- 동시 활성 시스템 수 제한: 강한 효과를 가진 GPU 시스템은 최대 동시 개수를 디자인 단계에서 정하고, 초과 시 저비용 대체 효과로 전환합니다.
- 오버드로우 관리: 반투명 파티클이 화면을 크게 덮으면 GPU 비용이 급증합니다. 스프라이트의 화면 면적·개수·중첩을 줄이고 컬링을 적용합니다. 알파만 0으로 낮춰도 셰이더 실행과 오버드로우가 자동으로 없어지지는 않습니다.
- 플랫폼별 품질 분기: 모바일/저사양 PC는 스폰율, 최대 파티클 수, 라이트 렌더러 사용 여부를 별도 프리셋으로 분기합니다.
- 틱 기반 업데이트 최소화: 블루프린트에서
Event Tick마다 파라미터를 밀어 넣기보다 값이 변할 때만 갱신하는 방식의 비용을 비교합니다. 모든 파라미터 갱신이 CPU-GPU 동기화 대기를 유발한다고 단정하지 않습니다. - LOD와 컬링 동시 적용: LOD만으로 부족하면 카메라 거리/화면 점유율 기준 컬링 룰을 함께 적용합니다.
프로파일링 도구 활용
어디서 성능 병목 현상이 발생하는지 정확히 파악하는 것이 최적화의 첫걸음입니다.
- 나이아가라 디버거(Niagara Debugger): 엔진 버전의 Niagara Debugger/Outliner에서 활성 시스템·이미터·파티클 수와 제공되는 성능 정보를 확인합니다. 모든 모듈의 정확한 CPU/GPU 비용이 기본 화면에 자동 표시되는 것은 아닙니다.
stat Niagara콘솔 명령어: 게임 플레이 중stat Niagara명령어를 콘솔에 입력하여 나이아가라 시스템의 전체적인 성능 통계를 확인할 수 있습니다.Unreal Insights: 더욱 심층적인 성능 분석을 위해 언리얼 엔진의 프로파일링 도구인Unreal Insights를 활용하여 필요한 CPU/GPU·메모리 트레이스 채널을 켜고 프레임 시간과 할당을 분석합니다. 같은 장면·카메라·품질·동시 효과 수에서 변경 전후를 비교합니다.
스크립트 최적화는 한 번에 끝나는 작업이 아니라, 효과를 개발하고 테스트하는 전 과정에 걸쳐 꾸준히 고려해야 할 부분입니다.
위에서 언급된 기본 기법들을 숙지하고 실제 작업에 적용함으로써, 여러분은 시각적으로 훌륭하면서도 성능적으로 효율적인 나이아가라 효과를 만들어낼 수 있을 겁니다.