Unity 내일배움캠프 TIL 1127 | 메모리 최적화를 위한 에셋 관리

cheeseonrose·2023년 11월 29일
0

Unity 내일배움캠프

목록 보기
87/89
post-thumbnail

2월 알쓸유잡 : 메모리 최적화를 위한 에셋 관리

💡 메모리에 영향을 미치는 Asset 관리



🍊 Asset Dependency

  • 중복 리소스 체크
    • 유니티는 중복 파일을 체크하지 않음
    • 실수로 동일한 파일을 다른 폴더에 넣지 않았는지 확인
  • Mesh, Material, Texture는 종속 관계가 존재 가능하다.
    • Ex : 탱크 오브젝트에서 사용하는 Material과 해당 Material이 사용하는 Texture
      → 탱크는 Material에 종속, Material은 Texture에 종속
  • 많은 종속 관계는 일대다 관계일 수 있다.
    → Asset Bundle 사용 시 중복 발생 가능
    • Ex : C Texture를 사용하는 A, B Material을 각각 다른 Bundle로 묶는 경우 Texture 중복 발생
      Addressables 사용 시 중복 관리가 수월함



🍋 Audio

  • Force To Mono
    • 쉽게 메모리 줄이기 가능
    • Stereo 정보를 없애고 Mono로 만들어줌
    • 모바일에서는 좋은 사운드 퀄을 요구하지 않기 때문에 사용해도 괜찮음
  • Load Type
    • 사운드 타입에 따라 적절하게 설정
      • 배경 음악은 빠른 속도 요구 X
      • 발소리, 총성, 타격음 등은 빠른 속도 요구
    • Decompress on Load (< 256kb)
      • 메모리에 올릴 때 압축을 풀어서 올림
      • 재생 속도가 매우 빠름
      • 재생 속도가 매우 빠르고 사이즈가 작은 오디오가 아니라면 사용하면 안 되는 옵션
    • Compressed into memory (< 1mb)
      • 압축을 한 상태에서 메모리에 올림
    • Streaming (> 1mb)
      • 배경 음악처럼 긴 음악들
  • Compression Format
    • 매우 짧은 클립은 ADPCM
    • 대부분의 경우는 Vorbis(ogg) 권장
      • iOS에서는 MP3 사용 이점이 적음
        • 일반적으로 iOS 앱 개발에는 MP3 사용이 권장되지만 (iOS가 MP3를 하드웨어 레벨에서 디코딩 가능하기 때문), 유니티는 디코딩을 소프트웨어로 처리하기 때문
  • Mute 되어도 메모리에는 존재한다.
    • 배경 음악 선택 옵션이나 바꿔야 하면 그때 그때 메모리에 올리고 내리는 방식으로 구현해야 함



🍏 Mesh

  • Mesh Compression은 저장 용량
    메모리와는 무관
  • Read/Write Enabled 옵션 해제할 것
    • 활성화하면 메모리 복제가 발생
      → API에서 런타임 중에 접근해서 Mesh를 변형하는 등의 작업을 위해 활성화하는 옵션
      → API에서 접근하는 것은 CPU에서, Mesh 사용은 GPU에서 하게 되므로 양쪽 메모리에 존재하게 됨
    • 2019.3 버전부터는 기본적으로 비활성화
  • 불필요하면 비활성화 해야 되는 옵션들
    • Rig
    • BlendShapes
    • Normal
    • Tangent
    • Lightmap UVs
    • Generate Colliders



🍑 Shader Variants

  • 패키지 용량 이슈가 크지만 메모리도 영향 있다.
  • 하나의 Shader는 수많은 바이너리 조각으로 파생된다.
    • 수많은 조건들의 조합 경우의 수
      • 노멀맵, 포그, 라이트맵, 인스턴싱, 플랫폼 등
  • 에디터에서의 작동 ≠ 플레이어 빌드에서의 작동
    • 에디터에서는 미리 모든 경우의 Shader를 만들어놓지 않음
      → 그때 그때 필요한 것들만 렌더링
  • Shader Variants를 줄이기 위한 기법들
    • Graphics API 지정 (Player Settings)
      • Graphics API마다 Variants를 만들어야 하므로 사용하는 API만 설정
    • Shader Stripping (Graphics / URP Settings)
      • 특정 옵션을 지정하면 다른 옵션과 연관된 Shader들은 만들지 않음
    • URP Asset에서 미 사용 기능 비활성화
    • multi_compile vs shader_feature
      • Shader 코드를 직접 작성할 때 고려
    • ShaderVariantCollection (Hiccup vs Memory)
      • 미리 Loading하게 되면 런타임 동안 프레임이 튀는 현상은 줄어들지만 미리 메모리를 선점하게 됨
      • 상황에 맞게 사용
    • Log Shader Compilation



🍒 Text Mesh Pro

  • 글자들을 미리 Texture로 제작한다.
  • 영미권 언어는 큰 문제가 없다.
  • 한글은 초성, 중성, 종성 조합 방식
  • 허용 글자 범위
    • 한글 : 2350자
      • 추가 129자
    • 모든 글자를 허용하게 되면 10000자를 넘게 됨
  • Static vs Dynamic
    • Static
      • 사용될 모든 문자 Atlas를 미리 생성
      • 런타임 시 원본 폰트가 필요 없음
      • 개발자가 예측 가능한 범위에 사용
    • Dynamic
      • 실시간으로 필요한 폰트 Atlas 갱신
      • 런타임 시 원본 폰트 필요
      • 사용 문자들의 범위를 예측 불가능할 때 유용
  • Multi Atlas Textures
    • Draw call vs 대역폭(Atlas Resolution)
    • 4096으로 하게 되면 모바일에서는 느려질 수 있음
    • 대역폭을 줄이게 되면 여러 개의 Atlas를 생성
      → Draw call Batching이 깨질 수 있음



🍇 Baked Lighting

  • Lightmap
    • Texture에 Lighting 결과를 미리 구워서 저장
    • static object에 적용
    • 저장 형태 : Texture2D
    • 넓은 씬에서는 Lightmap을 많이 만들어내므로 메모리 이슈 발생 가능성 있음
    • Subtractive, Baked Indirect, Shadowmask에 따라 Lightmap을 여러 개 만들어낼 수 있음
  • Light Probe
    • 주로 dynamic object 대응 용도 (static도 가능)
    • Diffuse term만 가능 (specular term 불가능)
    • 저장 형태 : 개당 float * 30 +
    • 메모리를 많이 차지하는 편은 아님
  • Reflection Probe
    • Specular term을 위한 데이터
    • 저장 형태 : 개당 Cubemap Texture
      • 내부적으로 Texture가 6개 들어감
    • 많이 사용할수록 메모리 이슈 발생 가능성 큼



🥭 Texture

  • 가능한 사이즈를 작게 할 것
  • 적절한 Texture Compression Format
  • 2D 및 UI는 SpriteAtlas 적극 활용할 것
  • Read/Write Enabled 옵션은 해제하기
  • Mipmap
    • 2D 및 UI에서는 대부분 필요 없음
    • 3D 게임에서는 필수



🥝 Texture Compression

  • PNG, JPEG 등 원본 이미지 Format과는 무관하다.
    • ETC, PVRTC, ASTC …
  • 기기별 지원되는 Texture Format 사용해야 한다.
    • 기기 미 지원 포맷 사용 시 압축이 풀릴 수 있음
  • 모바일에서는 ASTC 추천
    • 타겟 디바이스에 따라 다름
  • POT vs NPOT
    • Power of Two (256, 512, 1024…)
    • ASTC는 NPOT를 지원하지만 밉맵 사용 시 POT



🍍 POT vs NPOT

  • Power of Two (256, 512, 1024…)
    • 일반적으로 사용하는 Texture들은 POT 사이즈를 사용하도록 강제되어 왔음
  • ASTC는 NPOT(Not POT) 사이즈를 지원한다.
  • Mipmap 사용 시 POT 사용으로 강제된다.
    • 즉 3D 에셋용 Texture는 사실상 POT만 사용
  • UI 및 2D는 NPOT가 가능하다.
    • 하지만 Sprite Atlas 권장
    • Sprite Atlas는 POT



🍉 Mipmap

  • 가까이 있는 오브젝트는 고해상도 Texture를, 멀리 있는 오브젝트는 저해상도 Texture를 입혀서 메모리 대역폭을 효율적으로 만들어주는 것
  • 3D 게임에서는 무조건 활성화
  • 원본 Texture의 작은 버전을 여러 개 만들어냄 → 원래 Texture보다 33.333% 정도 메모리가 늘어남
  • 2D나 UI는 원근법이 필요 없기 때문에 Mipmap 사용 X
  • Texture LOD 같은 개념



🍐 Scene loading

  • Scene A 로드 → Scene B 로드 → Scene A 제거
    • Scene A에 대한 Resource가 있는 상태에서 Scene B에 대한 Resource도 메모리에 올라오게 되면 순간적으로 메모리가 터질 수 있음
      (Scene A, B의 메모리가 무거운 경우)
  • 무거운 Scene 사이를 이동할 때는 가벼운 중간 Scene을 Load 할 것을 권장



끗....!

0개의 댓글