icon

안동민 개발노트

9장 : 성능 최적화

환경 요소의 성능 분석


레벨 요소를 충분히 올렸다면, 이제는 보기 좋은 장면을 유지 가능한 성능으로 바꾸는 단계입니다.

레벨이 복잡해질수록 CPU/GPU/메모리 부담은 빠르게 커집니다. 그래서 성능 최적화(Performance Optimization)는 단순히 더 빠르게가 아니라, 다양한 기기에서 안정적인 프레임일관된 사용자 경험을 보장하는 과정입니다.


성능 최적화의 중요성 및 목표

성능 최적화는 게임 개발의 전 과정에 걸쳐 지속적으로 이루어져야 하는 작업입니다.

  • 프레임 속도 (FPS) 유지: 플레이어가 쾌적하게 게임을 즐기려면 안정적인 프레임 속도(초당 프레임 수)가 필수적입니다. 목표 FPS (예: PC 60 FPS, 모바일 30 FPS)를 달성하고 유지해야 합니다.
  • 다양한 하드웨어 지원: 저사양 기기에서도 게임이 원활하게 작동하도록 하여 더 많은 플레이어에게 접근성을 제공합니다.
  • 배터리 효율 (모바일): 모바일 게임의 경우, 최적화는 배터리 소모를 줄여 플레이 시간을 늘리는 데 기여합니다.
  • 개발 효율성: 최적화된 프로젝트는 빌드 시간 단축, 에디터 성능 향상 등 개발 과정 자체의 효율성도 높입니다.
  • 버그 감소: 성능 저하로 인한 물리 버그, 로딩 지연 등의 문제를 예방합니다.

성능 분석을 위한 기본 개념

성능 분석을 시작하기 전에 몇 가지 핵심 개념을 이해해야 합니다.

CPU (Central Processing Unit)

  • 역할: 게임 로직, 물리 시뮬레이션, AI 계산, 애니메이션 블렌딩, 드로우 콜(Draw Call) 준비 등 게임의 두뇌 역할을 하는 모든 계산을 담당합니다.
  • CPU 바운드 (CPU Bound): CPU가 GPU보다 느려 게임의 전체 프레임 속도를 제한하는 상태를 의미합니다.
  • 주요 병목 요인
    • 과도한 블루프린트/C++ 로직: Event Tick에서 너무 복잡한 계산을 수행.
    • 많은 액터 수: 레벨에 배치된 액터 수가 너무 많거나, 복잡한 로직을 가진 액터가 많을 때.
    • 물리 시뮬레이션: 동시에 많은 오브젝트가 물리 시뮬레이션될 때.
    • AI 계산: 복잡한 AI 로직이나 많은 수의 AI 캐릭터.
    • 드로우 콜: CPU가 GPU에게 렌더링할 오브젝트 목록을 전달하는 횟수. 드로우 콜 수가 많으면 CPU 오버헤드가 증가합니다.

GPU (Graphics Processing Unit)

  • 역할: 메시 렌더링, 셰이더 계산, 포스트 프로세싱, 그림자, 광원 계산 등 그래픽 관련 모든 작업을 담당합니다.
  • GPU 바운드 (GPU Bound): GPU가 CPU보다 느려 게임의 전체 프레임 속도를 제한하는 상태를 의미합니다.
  • 주요 병목 요인
    • 폴리곤 수: 화면에 보이는 총 폴리곤 수가 너무 많을 때.
    • 오버드로우 (Overdraw): 투명하거나 반투명한 오브젝트(파티클, 유리, 식물)가 많이 겹쳐 렌더링될 때.
    • 복잡한 셰이더/머티리얼: 연산량이 많은 복잡한 머티리얼 사용.
    • 그림자: 다수의 동적 그림자 또는 고해상도 그림자.
    • 포스트 프로세싱: 블룸, 앰비언트 오클루전, 스크린 스페이스 리플렉션 등 고비용 후처리 효과.
    • 광원: 동적 광원 수가 많거나, 넓은 범위에 영향을 미치는 광원.

언리얼 엔진의 성능 분석 도구

언리얼 엔진은 CPU와 GPU 병목 현상을 진단할 수 있는 다양한 도구를 제공합니다.

Stat 명령어

게임 플레이 중 (Alt + P 또는 Play 버튼) 콘솔 (Shift + ~ 키)에 입력하여 실시간 통계를 확인할 수 있습니다.

  • Stat FPS: 현재 프레임 속도(FPS)를 표시합니다. 가장 기본적인 성능 지표입니다.
  • Stat Unit
    • Game: CPU에서 게임 로직(블루프린트, AI, 물리) 처리 시간 (밀리초).
    • Draw: CPU에서 렌더링 명령을 GPU에 전달하는 시간 (드로우 콜 준비).
    • GPU: GPU에서 그래픽 렌더링 시간 (밀리초).
    • Frame: 총 프레임 시간 (밀리초).
    • 활용: Game 시간이 높으면 CPU 바운드, GPU 시간이 높으면 GPU 바운드를 의심할 수 있습니다. Draw 시간이 높다면 CPU가 드로우 콜 준비에 너무 많은 시간을 쓰고 있다는 의미입니다.
  • Stat Engine: 엔진의 다양한 서브시스템(렌더링, 물리, 애니메이션 등)의 CPU 시간을 상세하게 보여줍니다. Game 시간이 높을 때 어느 부분이 문제인지 더 깊이 파고들 때 사용합니다.
  • Stat SceneRendering: 렌더링 파이프라인의 각 단계에 대한 GPU 시간을 상세하게 보여줍니다. GPU 시간이 높을 때 어느 렌더링 단계가 문제인지 파악하는 데 유용합니다. (예: Lights, Translucency, PostProcess)
  • Stat RHI: 하위 수준 렌더링 인터페이스 통계를 보여줍니다.
  • Stat D3D12RHI / Stat VulkanRHI: 특정 그래픽 API에 대한 상세 통계를 보여줍니다.

ProfileGPU

  • 역할: GPU 렌더링 파이프라인의 각 단계에서 정확히 얼마의 시간이 소요되는지 계층적으로 보여주는 강력한 도구입니다.
  • 사용법: 게임 플레이 중 콘솔에 ProfileGPU를 입력합니다. 별도의 창이 뜨면서 상세한 GPU 통계가 표시됩니다.
  • 활용: Translucency (투명도, 파티클), PostProcess (후처리), ShadowDepths (그림자 깊이), BasePass (주요 메시 렌더링) 등 어느 렌더링 단계가 가장 많은 시간을 소모하는지 파악하여 GPU 병목의 근본 원인을 찾습니다.

뷰포트 시각화 모드

레벨 에디터 뷰포트 좌측 상단의 뷰 모드(View Mode) 드롭다운 메뉴에서 선택할 수 있습니다.

  • Overdraw (오버드로우): 투명/반투명 오브젝트가 겹쳐 렌더링되는 정도를 색상으로 보여줍니다. 흰색에 가까울수록 오버드로우가 심하여 GPU 부하가 높습니다. (예: 많은 파티클, 복잡한 식물)
  • Shader Complexity (셰이더 복잡도): 머티리얼의 셰이더 연산 복잡도를 색상으로 보여줍니다. 빨간색에 가까울수록 셰이더가 복잡하여 GPU 부하가 높습니다.
  • Light Complexity (광원 복잡도): 각 픽셀에 영향을 미치는 광원의 수를 색상으로 보여줍니다. 동적 광원이 많은 영역을 식별합니다.
  • Collision (충돌): 오브젝트의 충돌 메시를 시각적으로 보여줍니다. 불필요하게 복잡한 Complex Collision을 찾아낼 수 있습니다.
  • LOD Coloration (LOD 색상): 각 메시의 현재 LOD 레벨을 색상으로 보여줍니다. LOD가 적절하게 작동하는지, 너무 낮은 LOD가 사용되거나 너무 높은 LOD가 멀리서 사용되는지 확인합니다.
  • 활용: 시각적으로 병목 현상이 예상되는 부분을 빠르게 식별할 수 있습니다.

도구를 선택할 때는 질문 → 도구 → 지표 → 액션 순서로 매핑하면, 병목 원인을 추측이 아닌 데이터로 좁힐 수 있습니다.


환경 요소별 성능 분석 포인트

이제 실제 환경 요소들을 위 도구들을 사용하여 어떻게 분석하는지 알아봅시다.

메시 (Meshes)

  • Stat SceneRendering & Stat D3D12RHI: BasePass, DrawCalls 항목을 확인하여 화면에 보이는 메시의 총 폴리곤 수, 드로우 콜 수를 확인합니다.
  • LOD Coloration 뷰 모드: 메시 LOD가 적절하게 작동하는지 확인합니다. 너무 멀리 있는 오브젝트가 높은 LOD로 렌더링되고 있지 않은지 확인합니다.
  • 해결책
    • 불필요한 메시 폴리곤 감소 (리토폴로지, 최적화).
    • 적절한 LOD 설정 및 생성.
    • 하나의 메시로 합칠 수 있는 인접한 작은 메시들을 액터 병합 (Merge Actors) 기능으로 합쳐 드로우 콜 감소.

머티리얼 및 셰이더 (Materials & Shaders)

  • Shader Complexity 뷰 모드: 복잡한 셰이더를 사용한 오브젝트를 식별합니다.
  • ProfileGPU: BasePass 항목 내의 Shader 관련 비용을 확인합니다.
  • 해결책
    • 복잡한 셰이더 연산 (특히 픽셀 셰이더) 최소화.
    • 텍스처 샘플러 수 줄이기.
    • 불필요한 노드 제거.
    • Translucent (투명) 머티리얼 사용 최소화 (오버드로우 유발).

광원 (Lighting)

  • Light Complexity 뷰 모드: 동적 광원이 너무 많은 영역을 식별합니다.
  • Stat SceneRendering & ProfileGPU: Lights, ShadowDepths 항목을 확인하여 광원 계산 및 그림자 렌더링 비용을 분석합니다.
  • 해결책
    • 가능한 Static 또는 Stationary 광원을 사용하고 Movable 광원 수는 최소화.
    • 광원의 Attenuation Radius를 필요한 만큼만 작게 설정.
    • 그림자 품질 설정 조정.

파티클 및 특수 효과 (Particles & VFX)

  • Overdraw 뷰 모드: 투명 파티클의 오버드로우 정도를 확인합니다.
  • Stat SceneRendering & ProfileGPU: Translucency 항목을 확인하여 투명 오브젝트 렌더링 비용을 분석합니다.
  • 해결책
    • 파티클 스폰 속도 및 최대 파티클 수 제한.
    • 파티클 재질의 오버드로우 최소화 (Masked 재질 고려).
    • 파티클의 Cull Distance 설정.
    • GPU 파티클 시스템 (Niagara의 GPU Compute Sim) 고려.

물리 시뮬레이션 (Physics Simulation)

  • Stat Physics: 물리 오브젝트 수, 충돌 쌍 수, 물리 스텝 시간 등을 확인하여 CPU 병목을 진단합니다.
  • Collision 뷰 모드: 불필요하게 복잡한 충돌 메시를 식별합니다.
  • 해결책
    • Simple Collision 적극 활용, Complex Collision 사용 제한.
    • Simulate Physics 활성화 오브젝트 수 제한.
    • 물리 오브젝트 슬립 활용.
    • 고속 오브젝트에만 CCD 사용.

포스트 프로세싱 비용 분석

  • ProfileGPU: PostProcess 항목을 확인하여 후처리 효과의 비용을 분석합니다.
  • 해결책
    • 불필요한 후처리 효과 비활성화.
    • 각 효과의 품질(Intensity, Quality, Resolution 등) 설정 조정.

성능 분석 및 최적화 워크플로우

목표 설정: 프로젝트의 목표 플랫폼과 목표 FPS를 명확히 합니다.

측정 및 분석
  • 문제가 발생할 것으로 예상되는 영역(가장 복잡한 레벨, 오브젝트가 많은 곳)에서 테스트를 진행합니다.
  • Stat Unit, ProfileGPU, 뷰포트 시각화 모드 등 도구를 사용하여 병목 현상을 식별합니다.
  • CPU 바운드인지, GPU 바운드인지 먼저 파악합니다.

원인 식별: 분석된 데이터를 바탕으로 병목의 구체적인 원인(예: 과도한 오버드로우, 복잡한 셰이더, 너무 많은 물리 오브젝트)을 식별합니다.

최적화 적용: 식별된 원인에 맞춰 이 절에서 제시된 최적화 전략들을 적용합니다.

재측정 및 반복: 최적화를 적용한 후 다시 성능을 측정하여 개선 여부를 확인합니다. 만족할 만한 결과가 나올 때까지 이 과정을 반복합니다.

프로파일링 의사결정 순서 (실무용)

  1. Stat Unit으로 CPU/GPU 중 어디가 병목인지 먼저 고정합니다.
  2. CPU 병목이면 액터 틱, 물리, AI, 블루프린트 로직 순으로 비용을 줄입니다.
  3. GPU 병목이면 오버드로우, 그림자, 포스트 프로세스, 투명 머티리얼 순으로 줄입니다.
  4. 최적화 1회마다 동일한 카메라 위치/시나리오로 재측정하여 개선 폭을 기록합니다.
  5. 목표 FPS에 도달하면 품질 옵션(Scalability)별 하한선도 함께 검증합니다.

성능 병목 점검 체크리스트

  • Stat Unit 측정 결과를 스크린샷/로그로 남기고 개선 전후를 비교했는가?
  • 병목 원인을 추정이 아니라 ProfileGPU/시각화 모드로 확인했는가?
  • 최적화 후 아트 품질 저하(깜빡임, 그림자 깨짐, 반사 품질 저하)를 검수했는가?
  • 저사양/중간/고사양 프리셋에서 동일한 기능이 안정적으로 동작하는가?
  • 팀 내 성능 기준(FPS, 메모리, 로딩 시간)을 문서화했는가?

환경 요소 성능 분석은 프로젝트를 안정화하는 필수 단계입니다.

Stat 명령어, ProfileGPU, 뷰포트 시각화와 같은 도구를 활용해 병목을 수치로 확인하고, 요소별 개선 포인트를 반복 점검해 보세요. 꾸준한 분석과 조정이 최종 사용자 경험의 품질을 결정합니다.

목차