본문으로 건너뛰기
CHOI HONGSU
1 min read

UI 파티클 스프라이트 시트 베이커

UIParticle CPU Cost Reduction SpriteSheet Baker 기반 UI 파티클 최적화

Lobby / DraftBit 화면에서 UIParticle 사용 비중이 높아지면서, Canvas.SendWillRenderCanvases() 단계의 CPU 비용이 증가하는 문제가 있었습니다. 이 작업에서는 모든 UIParticle을 일괄 제거하지 않고, 화면에서 작게 보이거나 반복 재생되는 FX만 SpriteSheet로 베이크해 교체했습니다. 근접해서 보이거나 품질 차이가 큰 FX는 UIParticle을 유지해, 성능과 표현 품질 사이의 균형을 맞췄습니다. 이를 위해 Scene 기반 UIParticle Baker V2를 제작하고, 2-Pass Alpha 복원 / 슈퍼샘플링 / 자동 슬라이싱 / SpriteAnimationAsset 생성을 자동화했습니다.

Problem

Problem

UIParticle은 Canvas.SendWillRenderCanvases() 콜백을 통해 매 프레임 메시를 갱신합니다.

Lobby / DraftBit 화면에서는 UIParticle 사용량이 많았고, emitter가 많아질수록 콜백이 분산되어 CPU 비용이 증가했습니다.

최적화 전 Lobby 기준으로 Canvas.SendWillRenderCanvases() 구간에서 약 4.30ms가 측정되었고, UI 파티클이 CPU 프레임 예산의 부담 요소가 되고 있었습니다.

Approach

혼합 교체 (Mixed)

Chosen

Pros

  • 품질 손실 최소화

Cons

  • 스크린별 판단 필요

UIParticle 구조 개선만

Pros

  • 기존 FX 유지

Cons

  • 효과 제한적

Why 혼합 교체 (Mixed): 선택: 혼합 교체 화면상 작게 보이는 이펙트(Beat Gauge, 소형 반복 FX)는 SpriteSheet로 교체. 근접·대형·복잡한 FX는 품질 유지를 위해 UIParticle 유지

Implementation

  1. 01

    Scene 기반 UIParticle Baker V2 제작

    V1은 Prefab 기준 자동 프레이밍 방식이어서, 파티클의 실제 화면 구도나 카메라 배치를 세밀하게 맞추기 어려웠습니다.

    V2에서는 전용 Capture Scene을 생성하고, 아티스트가 Orthographic Camera와 World Space Canvas 위에서 파티클을 직접 배치한 뒤 촬영할 수 있도록 구성했습니다.

    이 방식으로 실제 UI에서 보이는 구도에 맞춰 SpriteSheet를 굽고, 베이크 결과의 품질을 더 쉽게 확인할 수 있게 했습니다.

  2. 02

    2-Pass Alpha 복원

    가산 블렌드 파티클은 단순 캡처만으로는 RGB와 Alpha를 안정적으로 분리하기 어렵습니다.

    이를 해결하기 위해 검정 배경과 흰 배경에서 각각 렌더링한 뒤, 두 결과를 비교해 Alpha와 RGB를 복원했습니다.

    • Black Background Capture
    • White Background Capture
    • Alpha 복원: α = 1 - (white - black)
    • RGB 복원: RGB = black / α

    이 과정을 통해 가산 블렌드 계열 UI 파티클도 배경색에 묻히지 않고 SpriteSheet로 변환할 수 있었습니다.

  3. 03

    슈퍼샘플링과 자동 슬라이싱

    SpriteSheet로 변환할 때 경계가 흐려지거나 계단 현상이 보이지 않도록 슈퍼샘플링 옵션을 추가했습니다.

    최대 8x 슈퍼샘플링으로 캡처한 뒤 최종 해상도로 다운샘플링하고, 결과 이미지를 자동으로 Sprite 단위로 슬라이싱했습니다.

    베이크가 끝나면 SpriteAnimationAsset을 자동 생성해, 기존 UIParticle 대신 UI Animation으로 바로 연결할 수 있도록 했습니다.

  4. 04

    UIParticle 컴포넌트 구조 정리

    SpriteSheet로 교체하지 않는 FX도 구조를 정리했습니다.

    기존에는 UIParticle 컴포넌트가 emitter마다 붙어 있어, emitter 수만큼 콜백이 분산되는 문제가 있었습니다.

    이를 Root에 1개의 UIParticle만 두는 구조로 통합해, 유지 대상 FX에서도 불필요한 콜백 중복을 줄였습니다.

  5. 05

    화면별 교체 심사

    Lobby / DraftBit 화면을 중심으로 FX 목록을 점검했습니다.

    화면에서 작게 보이거나 반복 재생되는 FX는 SpriteSheet로 교체하고, 품질 차이가 눈에 띄는 FX는 UIParticle로 유지했습니다.

    이 과정을 통해 성능만 기준으로 일괄 교체하지 않고, 화면 중요도와 시각적 손실을 함께 기준으로 판단했습니다.

Unity Profiler

Unity Profiler를 사용해 개발 빌드에서 UI 렌더링 관련 CPU 구간을 비교했습니다.

측정 구간은 UI Particle 교체 대상이 포함된 Lobby 화면 기준이며, SpriteSheet 교체 후 매 프레임 메시 갱신 비용이 줄어드는 것을 확인했습니다.

Validation

Tools: UnityProfiler · Build: Dev · Scene:  

DeviceGPUAPI
BeforeAfter
S21Mali G78Vulkan3.751.25

Before / After

UI Particle / SpriteSheet 비교

 

Before

기존 구조에서는 반복 재생되는 소형 UI FX도 UIParticle로 유지되어, 매 프레임 Canvas.SendWillRenderCanvases() 단계에서 메시 갱신이 발생했습니다.

특히 여러 emitter가 포함된 FX는 emitter 수만큼 갱신 비용이 누적되어, Lobby / DraftBit 화면에서 CPU 스파이크의 원인이 될 수 있었습니다.

After

화면에서 작게 보이거나 반복되는 FX는 SpriteSheet Animation으로 교체했습니다.

SpriteSheet는 미리 베이크된 프레임을 재생하기 때문에, 기존 UIParticle처럼 매 프레임 파티클 메시를 재구성하지 않아도 됩니다.

품질 차이가 큰 FX는 UIParticle로 유지하고, 유지 대상도 Root UIParticle 구조로 정리해 불필요한 콜백 중복을 줄였습니다.

BEFORE
AFTER

Conclusion

UIParticle을 모두 제거하는 대신, 화면별 중요도에 따라 SpriteSheet와 UIParticle을 혼합 사용하는 구조로 정리했습니다.

  • 소형 반복 UI FX는 SpriteSheet로 베이크해 교체
  • 근접 / 대형 / 복잡한 FX는 UIParticle 유지
  • Scene 기반 Baker V2로 실제 UI 구도에 맞춘 캡처 가능
  • 2-Pass Alpha 복원으로 가산 블렌드 파티클의 RGB / Alpha 분리
  • 자동 슬라이싱과 SpriteAnimationAsset 생성으로 교체 작업 자동화
  • 유지 대상 UIParticle은 Root 1개 구조로 정리해 콜백 중복 감소

Galaxy S21 / Vulkan 개발 빌드 기준, 교체 대상 화면에서 UI 파티클 관련 CPU 구간이 3.75ms에서 1.25ms로 감소했습니다.

Tradeoffs & Future Work

Tradeoffs

  • SpriteSheet 방식은 매 프레임 파티클 메시를 갱신하지 않아 CPU 비용을 줄일 수 있지만, 프레임 이미지로 고정되기 때문에 실시간 파티클처럼 동적인 변화에는 한계가 있습니다.
  • SpriteSheet 텍스처가 추가되므로, 모든 FX를 무조건 변환하면 텍스처 메모리와 아틀라스 관리 비용이 증가할 수 있습니다.