안동민 개발노트

본문 시작

에셋과 레벨 최적화 기법

메시 LOD·텍스처 크기·머티리얼 복잡도와 레벨 스트리밍을 조정해 체감 품질을 지키면서 렌더링 비용을 줄입니다.

병목을 찾는 도구를 익혔다면, 이제는 실제로 비용이 큰 자산을 줄여야 성능이 올라갑니다.

같은 장면이라도 메시 밀도, 텍스처 크기, 머티리얼 복잡도, 레벨 구성 방식에 따라 프레임 차이가 크게 벌어집니다.

이번 절에서는 에셋(Asset)과 레벨(Level)을 대상으로 즉시 적용 가능한 최적화 기법을 정리합니다.

핵심은 무작정 화질을 낮추는 것이 아니라, 플레이어가 체감하기 어려운 영역부터 비용을 줄이는 순서를 잡는 것입니다.

이 절을 마치면 어떤 항목을 얼마나 줄일지 근거를 가지고 결정할 수 있습니다.


에셋 및 레벨 최적화의 목표

에셋 및 레벨 최적화는 게임의 성능을 좌우하는 핵심 요소입니다.

  • 렌더 제출 비용 감소: 드로우콜, 머티리얼 섹션 수, 렌더 상태 변경, RHI 제출 비용을 함께 줄입니다.
  • 기하 비용 조정: 모바일, 비 Nanite, 스켈레탈 메시, 폴리지처럼 폴리곤 수가 직접 부담이 되는 대상을 먼저 줄입니다.
  • 텍스처 메모리 사용량 조정: 텍스처가 차지하는 VRAM, 스트리밍 풀, 디스크 크기, 압축 품질을 함께 봅니다.
  • 오버드로우 감소: 투명하거나 반투명한 부분이 겹쳐 그려지는 횟수와 픽셀 셰이더 비용을 줄입니다.
  • 그림자와 조명 비용 조정: 그림자 맵, 동적 광원, Lumen/라이트맵 선택이 만드는 런타임 비용과 메모리를 나눕니다.
  • 데이터 크기 감소: 게임의 빌드(Binary) 크기와 런타임 메모리 사용량을 줄입니다.

메시 (Mesh) 최적화

가장 기본적이면서도 중요한 최적화 대상은 3D 모델, 즉 메시입니다.

폴리곤 수 감소 (Poly Count Reduction, 모바일 우선)

  • 필요성: 모바일, 비 Nanite 메시, 스켈레탈 메시, 폴리지에서는 화면에 보이는 폴리곤 수가 렌더링 부담으로 이어질 수 있습니다. UE5/Nanite 환경에서는 폴리곤 수만 보지 말고 화면 픽셀 비용, 머티리얼, 오버드로우, 그림자 비용을 같이 봅니다.
  • 방법
    • 리토폴로지 (Retopology): 외부 3D 모델링 툴(Blender, Maya, ZBrush 등)에서 모델의 폴리곤 밀도를 최적화합니다.
    • 디시메이션 (Decimation): Static Mesh Editor의 LOD Group 또는 각 LOD의 Reduction Settings로 자동 단순화를 조정합니다. 원본 메시 자체의 편집은 Modeling Mode 등 별도 도구와 구분합니다.
      • 주의: 너무 줄이면 디테일 손실이 크거나 외형이 깨질 수 있으므로, 육안으로 확인하며 적절한 수준을 찾아야 합니다.
    • 불필요한 디테일 제거: 플레이·그림자·반사·충돌 어느 경로에도 필요 없는 면만 제거합니다. 벽 뒷면 제거로 빛샘이나 반사 누락이 생기지 않는지 확인합니다.

LOD (Level of Detail)

  • 필요성: 멀리 있는 오브젝트는 가까이 있는 오브젝트만큼 디테일할 필요가 없습니다. LOD는 거리나 화면 크기에 따라 메시, 애니메이션, 머티리얼 비용을 낮추는 장치입니다. Nanite 사용 여부와 플랫폼 제약에 따라 효과와 설정 방식이 달라집니다.
  • 설정

    Static Mesh Editor를 엽니다.

    Details 패널의 LOD Settings에서 LOD Group 프리셋 또는 LOD 수를 선택합니다.

    외부 LOD를 가져오거나 각 LOD의 Reduction Settings를 조정한 뒤 Apply Changes로 자동 생성 결과를 적용합니다. 메뉴 이름은 버전에 따라 다를 수 있습니다.

    각 LOD의 Screen Size를 조절하여 화면에서 메시가 차지하는 크기에 따른 전환 기준을 정의합니다. 고정된 월드 거리와는 다릅니다.

    LOD Coloration 뷰 모드 (뷰 모드 > LOD 색상)를 사용하여 각 LOD가 언제 활성화되는지 시각적으로 확인합니다.

  • 팁: 수동으로 만든 LOD가 자동 생성된 LOD보다 품질이 좋고 효율적일 수 있습니다.

충돌 메시 최적화

  • 필요성: 물리 시뮬레이션의 성능에 가장 직접적인 영향을 미칩니다.
  • 방법: 7장 5절 물리 시뮬레이션 성능 조정에서 다룬 것처럼, Simple Collision (단순 충돌)을 적극적으로 사용합니다.
    • Static Mesh Editor에서 Collision 메뉴를 통해 Add Box/Sphere/Capsule Simplified Collision 또는 Auto Convex Collision을 사용하여 단순 충돌을 생성합니다.
  • 복잡 충돌은 필요한 정밀 쿼리에 선택적으로 사용합니다. Use Complex as Simple로 삼각형 메시를 쓰는 바디 자체는 물리 시뮬레이션할 수 없으므로, 움직이는 물리 오브젝트에는 단순 충돌을 준비합니다.

텍스처 (Texture) 최적화

텍스처는 VRAM 사용량에 큰 영향을 미칩니다.

해상도 조정 (Resolution Adjustment)

  • 필요성: 텍스처 해상도가 높을수록 더 많은 VRAM을 소모합니다.
  • 방법
    • 텍스처 에셋 더블클릭: Details 패널의 Compression Settings와 Max Texture Size를 조정합니다.
    • Max Texture Size: 텍스처의 최대 해상도를 제한합니다. (예: 2048x2048 대신 1024x1024)
    • Power of 2 (2의 거듭제곱): 밉맵과 스트리밍·압축 제약을 고려해 2의 거듭제곱(예: 256, 512, 1024, 2048)을 기본으로 검토합니다. UI 등 비거듭제곱 텍스처가 적합한 용도도 있습니다.
  • 활용: 멀리 있거나 중요하지 않은 오브젝트의 텍스처는 낮은 해상도를 사용합니다.

압축 설정 (Compression Settings, 플랫폼별)

  • 필요성: 플랫폼별 GPU 압축 포맷과 알파 채널 유무에 따라 VRAM, 디스크 크기, 품질이 달라집니다.
  • 방법: 텍스처 에셋의 Details 패널에서 Compression Settings를 선택합니다.
    • 플랫폼별 포맷: 데스크톱은 BCn 계열, 모바일은 ASTC/ETC 계열처럼 대상 플랫폼에 맞는 압축 포맷이 사용됩니다.
    • Normalmap: 노멀 맵에 사용됩니다.
    • VectorDisplacementmap: 변위 맵에 사용됩니다.
    • UserInterface2D (RGBA): 압축 손실을 피할 UI 등에 검토하며, 메모리 비용을 확인합니다. 알파가 있다는 이유만으로 이 포맷이 필수인 것은 아닙니다.
    • Masks (R, G, B, A): 채널별로 독립적인 데이터를 담는 마스크 텍스처에 사용됩니다. (예: AO, Roughness, Metallic을 하나의 텍스처에 묶을 때)
  • 팁: 불필요한 알파 채널을 제거하거나, 여러 흑백 맵(AO, Roughness, Metallic)을 하나의 텍스처의 각 채널에 넣어 VRAM 사용량을 절약하는 것이 좋습니다.

밉맵 (Mipmap)

  • 필요성: 밉맵은 텍스처의 여러 해상도 버전을 추가로 만들기 때문에 원본 대비 데이터가 늘어납니다. 대신 거리별로 낮은 mip을 사용해 샘플링 품질, 텍스처 캐시 효율, 스트리밍 안정성을 높입니다.
  • 설정: 대부분의 텍스처는 기본적으로 밉맵이 활성화되어 있습니다. 텍스처 에셋의 Details 패널에서 Mip Gen Settings를 확인합니다. (UI 텍스처처럼 밉맵이 불필요한 경우 NoMipmaps로 설정)

머티리얼 (Material) 최적화

복잡한 머티리얼은 셰이더 연산 부하를 증가시킵니다.

셰이더 복잡도 감소

  • 필요성: 머티리얼 비용은 단순한 노드 수보다 shader instruction, texture fetch, 분기, permutation, 오버드로우에 더 크게 좌우됩니다.
  • 방법
    • Shader Complexity 뷰 모드: 비용이 클 것으로 추정되는 영역을 찾고 실제 GPU 시간과 대조합니다.
    • 최적화
      • 불필요한 노드 제거.
      • 연산량이 많은 노드 대신 간단한 수학 연산 사용.
      • Static Switch Parameter로 사용하지 않는 분기를 컴파일 시 제거하되, 조합에 따른 셰이더 permutation 증가 확인.
      • 여러 머티리얼의 중복 로직은 Material Function으로 관리. 함수화 자체가 런타임 연산을 공유하거나 줄이지는 않음.
      • 마스터 머티리얼 - 인스턴스 (Master Material - Instance) 패턴을 사용하여 스칼라·벡터 등의 파라미터를 조절합니다. 정적 스위치 변경은 새 셰이더 조합의 컴파일이 필요할 수 있습니다.
  • 팁: 조명 반응이 필요 없는 배경, UI, 특수 효과는 Unlit을 검토할 수 있습니다. 조명 정보가 필요한 표면까지 무리하게 바꾸면 품질 기준이 흔들립니다.

오버드로우 감소 (Overdraw Reduction)

  • 필요성: 투명/반투명 머티리얼(유리, 물, 파티클, 식물 잎)은 겹쳐질수록 여러 번 렌더링되어 GPU 부하를 크게 증가시킵니다.
  • 방법
    • Shader Complexity & Quads / Quad Overdraw: 오버드로우가 심한 부분을 식별합니다.
    • 블렌드 모드 선택: 가능하면 Opaque를 우선하고, Translucent가 필요한 경우 면적과 겹침을 줄입니다. Masked는 정렬/블렌딩 부담을 낮출 수 있지만 알파 테스트와 픽셀 비용이 남으므로 Shader Complexity와 Quad Overdraw로 확인합니다.
    • 투명 오브젝트 수 제한: 한 화면에 보이는 투명 오브젝트의 수를 줄입니다.
    • 파티클 최적화: 파티클 시스템에서 파티클의 수, 크기, 수명, 텍스처 오버드로우를 최소화합니다.

레벨 (Level) 최적화

레벨 구성 방식도 성능에 큰 영향을 미칩니다.

액터 병합 (Merge Actors)

  • 필요성: 여러 작은 스태틱 메시 액터를 병합하면 렌더 제출 비용을 줄일 수 있습니다. 다만 머티리얼 섹션 수가 남아 있거나 오클루전/LOD 단위가 커지면 이득이 줄어들 수 있으므로 병합 전후를 비교해야 합니다.
  • 사용법: 레벨 에디터에서 병합할 액터들을 모두 선택한 후, UE5 상단 Actor > Merge Actors에서 방식과 설정을 선택합니다. 구버전은 Window > Developer Tools에 있습니다.
  • 활용: 건축물 구성 요소(벽, 창문, 기둥)나 작은 오브젝트 그룹(돌 무더기, 나뭇가지 묶음)에 효과적입니다.
  • 주의: 하나의 메시로 합친 원래 부품은 독립적으로 움직이지 않습니다. 병합 결과에도 LOD를 구성할 수 있지만 원래 액터별 컬링·LOD 단위는 달라지므로 따로 움직일 부품은 분리합니다.

컬링 (Culling)

  • 필요성: 화면에 보이지 않는 오브젝트는 렌더링되지 않도록 하여 성능을 절약합니다.
  • 종류
    • 프러스텀 컬링 (Frustum Culling): 주 카메라 시야 밖의 오브젝트를 해당 뷰에서 제외합니다. 그림자·반사 등 다른 패스에는 필요할 수 있습니다.
    • 오클루전 컬링 (Occlusion Culling): 가려진 오브젝트를 bounds와 가시성 결과에 따라 제외합니다. 판정 비용과 지연, 렌더링 경로별 차이가 있으므로 완벽한 즉시 제거로 가정하지 않습니다.
    • 거리 컬링 (Distance Culling): 특정 거리 밖에 있는 오브젝트는 아예 렌더링되지 않도록 설정합니다.
      • 설정: Static Mesh Component의 Rendering 섹션에서 Min Draw Distance, Desired Max Draw Distance, Current Max Draw Distance를 확인하거나, 여러 액터에는 Cull Distance Volume을 사용합니다.
    • LOD와 컬링 분리: LOD는 표시 품질을 단계적으로 낮추는 장치이고, 완전 제거는 거리 컬링 또는 Cull Distance Volume 기준으로 관리합니다.

조명 방식 선택

  • Static Lighting: 빌드 후 런타임 조명 비용은 낮지만 라이트맵 메모리, 빌드 시간, 동적 변화 제약이 생깁니다.
  • Stationary Lighting: 정적/동적 요소를 섞을 수 있지만 overlap 제한과 동적 그림자 비용을 함께 관리해야 합니다.
  • Movable/Lumen: 실시간 변화와 동적 GI가 필요한 경우에 적합하지만, 그림자와 반사 비용을 ProfileGPU에서 확인해야 합니다. Lumen 중심 프로젝트에서는 precomputed static lighting 사용 여부도 프로젝트 설정과 함께 봅니다.

프로파일링 및 반복

  • 측정 루프: 최적화는 분석 -> 적용 -> 재측정 -> 재분석의 반복 과정입니다.
  • 단계적 접근: 한 번에 너무 많은 것을 바꾸지 말고, Stat Unit, ProfileGPU, Shader Complexity, Quad Overdraw, texture streaming 통계를 통해 움직인 지표를 기록합니다.

적용 후 비교

  • 같은 카메라에서 변경 전후 프레임 시간과 메모리를 기록합니다.
  • LOD 전환, 압축 손실, 빛샘, 충돌과 개별 액터 조작이 유지되는지 확인합니다.
  • 개선이 작거나 품질이 기준을 벗어나면 변경을 되돌리고 다음 비용 후보를 검토합니다.
  • 큰 월드는 World Partition 또는 레벨 스트리밍의 로드 범위도 함께 확인합니다. LOD·컬링과 실제 데이터 언로드는 서로 다른 동작입니다.