icon
5장 : 기본 스크립팅과 수학

스크립트 최적화 기본 기법


나이아가라는 매우 강력하고 유연한 파티클 시스템이지만, 그만큼 비효율적으로 사용될 경우 성능에 큰 부담을 줄 수 있습니다. 특히 복잡한 효과를 만들거나 많은 파티클을 사용할 때는 스크립트 최적화(Script Optimization) 가 필수적입니다. 최적화는 단순히 "빠르게" 만드는 것을 넘어, 여러분의 효과가 다양한 하드웨어에서 안정적으로 작동하고 게임의 전체적인 프레임 레이트(Frame Rate)를 저하시키지 않도록 보장하는 중요한 과정입니다.

이 절에서는 나이아가라 스크립트의 성능을 향상시키기 위한 몇 가지 기본적인 최적화 기법에 대해 알아보겠습니다.


왜 최적화해야 할까요?

나이아가라 시스템은 매 프레임마다 수천, 수만 개의 파티클에 대한 수백 가지의 계산을 수행할 수 있습니다. 각 계산이 아무리 사소해 보여도, 이들이 쌓이면 엄청난 연산량이 됩니다. 특히 다음과 같은 경우에 최적화의 필요성이 더욱 커집니다.

  • 많은 파티클 수: 동시에 활성화되는 파티클 수가 많을수록 각 파티클에 대한 연산 부담이 커집니다.
  • 복잡한 모듈 로직: 복잡한 수학 연산, 조건문, 데이터 인터페이스 호출 등이 많을수록 연산 시간이 늘어납니다.
  • 성능 민감한 플랫폼: 모바일 기기, VR 등 사양이 제한적인 플랫폼에서는 작은 최적화로도 큰 성능 향상을 기대할 수 있습니다.
  • 다수의 이펙트 동시 재생: 여러 나이아가라 효과가 한 화면에 동시에 재생될 때, 각각의 최적화가 전체 성능에 영향을 미칩니다.

불필요한 계산 피하기

가장 기본적인 최적화는 '불필요한 일을 하지 않는 것'입니다.

  • 사용하지 않는 모듈 제거: 이미터에 추가되어 있지만 실제로는 아무런 기능도 하지 않거나, 더 이상 필요 없는 모듈은 과감하게 삭제하세요. 각 모듈은 나름의 연산 비용을 가집니다.
  • 조건문을 활용한 계산 제한: 특정 조건에서만 실행되어야 하는 복잡한 계산이 있다면, If 노드를 사용하여 해당 조건이 만족될 때만 계산이 수행되도록 합니다.
    • 예시: 파티클이 땅에 닿았을 때만 마찰력을 계산한다면, OnGround와 같은 조건 Bool 값을 사용하여 마찰력 계산을 If 노드 안에 넣습니다.
  • 불필요한 데이터 인터페이스 호출 자제: 데이터 인터페이스는 외부 데이터를 가져오는 데 비용이 발생합니다. 필요한 경우에만 호출하고, 같은 데이터를 여러 번 가져오기보다 한 번 가져와서 여러 곳에서 재사용하는 것이 좋습니다.

계산량 줄이기

같은 결과를 얻더라도 더 적은 연산으로 얻을 수 있는 방법을 찾아야 합니다.

  • 간단한 수학 연산 선호: Lerp (선형 보간)는 Sine이나 Power 같은 복잡한 수학 함수보다 일반적으로 더 효율적입니다. 가능하다면 간단한 연산으로 대체할 수 있는지 고려해 보세요.
  • 정규화(Normalize)의 오용 주의: Normalize 연산은 제곱근(Sqrt) 계산을 포함하므로 비교적 비용이 큽니다. 벡터의 방향만 필요하고 실제 크기 자체는 필요 없을 때만 사용합니다. 크기 비교를 해야 할 때는 Vector Length 대신 Vector Length Squared를 사용하여 제곱근 계산을 피하는 것이 좋습니다.
    • Vector Length Squared는 $\textLength^2 = x^2 + y^2 + z^2$ 로 계산되어 더 빠릅니다.
  • 상수 vs. 변수: 스크립트 내에서 값이 변하지 않는 상수는 직접 값을 입력하는 것이 좋습니다. 불필요하게 Get 노드를 통해 매 프레임마다 가져오는 것은 작은 오버헤드를 발생시킬 수 있습니다.
  • 복잡한 커브 최소화: 커브는 시각적으로 아름다운 변화를 제공하지만, 너무 많은 키나 복잡한 탄젠트를 가진 커브는 계산 비용을 증가시킬 수 있습니다. 필요한 만큼만 키를 사용하고 부드럽게 유지하세요.

GPU와 CPU 연산의 이해

나이아가라는 파티클 시뮬레이션을 CPU 또는 GPU에서 수행할 수 있습니다. 각 방식의 장단점을 이해하고 적절히 활용하는 것이 중요합니다.

  • GPU 시뮬레이션 활용
    • 대규모 파티클 효과(수천, 수만 개)에는 GPU 시뮬레이션이 훨씬 효율적입니다. GPU는 병렬 연산에 특화되어 있어, 각 파티클이 독립적으로 계산되는 경우 CPU보다 압도적으로 빠릅니다.
    • 주의: GPU 시뮬레이션은 월드와의 충돌 처리, 블루프린트와의 양방향 통신 등 특정 CPU 기반 기능에 제약이 있을 수 있습니다. 모든 상황에 GPU 시뮬레이션이 최적은 아닙니다. 이미터의 Sim Target 속성을 GPU Compute로 설정하여 변경할 수 있습니다.
  • CPU 시뮬레이션 선택
    • 정확한 충돌 처리, 복잡한 게임 로직과의 연동(블루프린트에서 파티클 데이터 읽기/쓰기), 적은 수의 파티클에는 CPU 시뮬레이션이 더 적합할 수 있습니다.
    • 소규모 효과의 경우 CPU 시뮬레이션의 오버헤드가 크지 않으므로 굳이 GPU로 전환할 필요는 없습니다.

LOD (Level of Detail) 및 스케일러빌리티

나이아가라는 거리에 따라 효과의 복잡도를 자동으로 조절하는 기능을 제공합니다.

  • Scalability 섹션 활용: 이미터의 Scalability 섹션에서 Max Particles, Cull Proxy, LOD Distance 등의 속성을 설정할 수 있습니다.
    • Max Particles: 한 이미터에서 동시에 생성될 수 있는 최대 파티클 수를 제한하여 과도한 파티클 생성을 방지합니다.
    • LOD Distance: 카메라와의 거리에 따라 이미터의 스폰율, 파티클 수, 또는 특정 모듈의 활성화 여부 등을 자동으로 조절하여 멀리 있는 효과는 간단하게 렌더링하도록 합니다. 이를 통해 보이지 않거나 중요하지 않은 효과에 대한 연산 비용을 크게 줄일 수 있습니다.
  • Deactivate after System Last Particle Dies: 시스템 속성에서 이 옵션을 활성화하면, 모든 파티클이 사라진 후 시스템이 자동으로 비활성화되어 불필요한 연산을 방지합니다.

프로파일링 도구 활용

어디서 성능 병목 현상이 발생하는지 정확히 파악하는 것이 최적화의 첫걸음입니다.

  • 나이아가라 디버거(Niagara Debugger): 나이아가라 에디터의 Debug 패널이나 언리얼 에디터의 Window > Developer Tools > Niagara Debugger를 통해 파티클 수, 프레임 시간, 각 모듈의 비용 등을 실시간으로 확인할 수 있습니다.
  • stat Niagara 콘솔 명령어: 게임 플레이 중 stat Niagara 명령어를 콘솔에 입력하여 나이아가라 시스템의 전체적인 성능 통계를 확인할 수 있습니다.
  • Unreal Insights: 더욱 심층적인 성능 분석을 위해 언리얼 엔진의 프로파일링 도구인 Unreal Insights를 활용하여 CPU/GPU 사용량, 메모리 할당 등을 정밀하게 분석할 수 있습니다.

스크립트 최적화는 한 번에 끝나는 작업이 아니라, 효과를 개발하고 테스트하는 전 과정에 걸쳐 꾸준히 고려해야 할 부분입니다. 위에서 언급된 기본 기법들을 숙지하고 실제 작업에 적용함으로써, 여러분은 시각적으로 훌륭하면서도 성능적으로 효율적인 나이아가라 효과를 만들어낼 수 있을 겁니다.