텍스처 압축으로 유니티 모바일 게임 메모리 최적화하기

Sang Hun
더핑크퐁컴퍼니 기술 블로그
12 min readDec 21, 2022

해당 게시물은 Unity 2020.3.15f2 버전을 사용했으며, 테스트 기기는 iPhone7(64GB, iOS 16.1.1)을 사용했습니다.

안녕하세요, 더핑크퐁컴퍼니 서비스개발팀에서 Unity를 활용해 게임 컨텐츠를 개발하고있는 벨로(bello)입니다.

이번 글에선 최적화의 필요성과 텍스처의 개념 그리고 텍스처 압축 포맷에 대해 설명하도록 하겠습니다.

최적화가 왜 필요한지?

현재까지 <아기상어 키즈 월드> 앱 프로젝트에서는 간단한 2D 게임을 제작하고 있어 최적화에 대해 깊게 생각해본 적은 없었습니다. 하지만 앞으로 출시할 게임들은 이전 게임들보다는 조금 더 많은 파티클, 모션 그리고 좋은 퀄리티의 이미지 등 게임의 퀄리티를 높이기 위해 더 많은 리소스를 사용할 것입니다.

저희 앱의 주요 대상이 아이들인 만큼 부모의 기기를 사용하는 아이들도 있겠지만, 아이들이 사용하는 기기는 대부분 저사양의 기기로 예상합니다. 따라서 이 저사양 기기에서 게임이 정상적으로 실행되기 위해선 늘어난 리소스만큼 메모리를 최적화하는 작업이 필요하다고 생각됩니다.

Unity에서 모바일 게임 성능을 최적화하는 방법은 여러가지가 있습니다. SciptableObjects 사용, 스크립트 최적화, 물리 처리 최적화, 텍스처 최적화, 렌더링 최적화 등 다양한 방법으로 성능을 최적화할 수 있습니다. 이번 글에선 텍스처 최적화 중 텍스처 압축에 대해 알아보겠습니다.

텍스처란?

텍스처란 이미지를 GPU에서 사용하기 위해 렌더링한 것을 텍스처라고 하며, GPU 메모리에 직접 로드되므로 렌더링 중에 매우 효율적으로 액세스할 수 있습니다.

Unity에서 텍스처는 게임 오브젝트를 덮거나 래핑하는 이미지 또는 동영상 파일로 시각적 효과를 만들어 냅니다.

텍스처 압축 이란?

jpg, png 등 익숙하게 알고 있는 이미지 포맷은 디스크에 저장하는 용량 효율을 위해 제작된 알고리즘으로 GPU에서 바로 읽어올 수가 없습니다. 따라서 GPU에서 읽는 전용 포맷으로 변환을 해줘야 하는데, Unity는 이 기능을 제공하고 있습니다.

이를 모르고 간혹 성능을 위해 jpg, png, psd 등을 고려하는 데 이미지 포맷과 전혀 상관없이 Unity에서 이미지를 사용할 때 GPU에서 사용하는 포맷으로 변경하기 때문에 이미지 포맷은 편한 것을 사용하면 됩니다.

픽셀당 비트(bpp)는 단일 텍스처 픽셀에 필요한 스토리지 용량입니다. bpp 값이 더 낮은 텍스처는 디스크와 메모리를 더 적게 차지합니다. bpp 값이 낮으면 GPU가 텍스처 픽셀을 읽는 데 더 적은 메모리 대역폭을 사용합니다. GPU 메모리 대역폭은 종종 프레임 속도 병목 현상을 유발할 수 있으므로, 텍스처 압축을 사용하면 이러한 문제를 방지할 수 있습니다.

텍스처 에셋의 화질이 높을수록 픽셀당 비트가 더 높으며, 그에 따라 빌드 크기, 로드 시간, 런타임 메모리 사용량이 늘어납니다. 모든 텍스처 압축 포맷에는 어느 정도 손실이 있습니다. 압축되지 않은 텍스처는 최고의 품질을 제공하지만, 픽셀당 비트도 가장 높습니다. 모든 텍스처 압축 포맷은 제각기 서로 다른 장단점을 지니고 있습니다.

텍스처 압축 포맷의 종류

Unity에서 주로 사용하게 되는 텍스처 압축 포맷은 DXT, PVRTC, ETC1, ETC2, ASTC 등이 있습니다.

RGBA 무압축

  • 압축을 하지 않는 포맷으로 R,G,B,A각 채널에 8비트를 사용해 픽셀당 32비트를 사용합니다.
  • Alpha채널을 사용하지 않는 경우 24비트를 사용합니다.
  • 원본 이미지의 크기와 동일합니다.

DXT1 (DirectX Texture 1)

  • Direct X10 이상에선 BC1이라고도 불립니다.
  • 두 가지의 경우가 있는데, Alpha채널 사용 여부에 따라 A1R3G3B3인 경우와 R4G4B4인 경우가 있습니다.
  • 가장 기본적인 형식으로, 16픽셀 데이터를 64비트 블록으로 변환합니다.
  • 각 블록은 두 개의 16비트 RGB 5:6:5 색상 극단 값과 각 픽셀당 2비트씩, 총 32비트의 테이블을 가져 총 4개의 색상을 이용할 수 있습니다.
  • 압축 효율은 높지만, 제대로 된 알파 색상을 지원하지 않기 때문에 주로 알파채널이 없는 이미지를 압축할 때 쓰입니다.

PVRTC (Power VR texture compression)

  • 주로 iOS에서 사용하는 압축 포맷입니다.
  • DXT1 압축 포맷과 방식이 비슷하며 차이점은 블록 경계를 뭉개며 블러링을 시켜줍니다.
  • 블록 경계를 뭉개면서 컬러를 침범하는 경우가 발생할 수 있습니다. (block artifact)
  • 픽셀당 알파채널 포함 4비트이므로 32비트인 원본에 비해 1/8의 압축 효율을 보여줍니다.
  • 4bpp, 2bpp 두 가지 모드가 있으며, ARGB 데이터를 지원한다는 점에서 ETC와 차이가 있습니다.

ETC1 (Ericsson Texture Compression 1)

  • 모든 OpenGL ES 2.0을 지원하는(Froyo 이상) Android 기기에서 사용할 수 있는 압축 포맷입니다.
  • 픽셀당 Alpha채널 없이 4비트로 24비트인 원본에 비해 1/6의 압축 효율을 보여줍니다.
  • 대부분은 품질이 좋지만, PVRTC와 다르게 알파채널을 지원하지 않는다는 단점이 있습니다.

ETC2 (Ericsson Texture Compression 2)

  • ETC2 압축 포맷은 ETC1를 확장 및 개선해 알파채널을 포함하는 압축 포맷입니다.
  • ETC2는 Open GL ES 3.0 이상에서만 지원됩니다. 갤럭시 S3 이하 등의 구형 기종에서는 Open GL ES 2.0으로 돌아가기 때문에 ETC2를 사용하는 것이 불가능합니다.
  • OpenGL ES 2.0 기기에 ETC2 포맷을 사용하게 되면 작동하는 데에는 문제가 없지만, 성능상 효율이 떨어지게 됩니다.

ASTC (Adaptive Scalable Texture Compression)

  • ASTC는 DXT 및 ETC와 같은 다른 텍스처 압축 포맷보다 좀 더 효율적이고 유연한 대안이 되도록 설계되었습니다. 블록 기반 압축, 엔트로피 인코딩 및 가변 블록 크기를 포함한 기술 조합을 사용하여 품질과 압축 비율 간의 적절한 균형을 달성합니다.
  • ASTC는 ETC, PVRTC와 다르게 POT(Power Of Two)텍스처를 사용하지 않아도 텍스처를 압축할 수 있습니다. 아래에서 보여드리겠지만, 만약 ETC와 PVRTC사용할 때 POT텍스처를 사용하지 않는다면 오히려 메모리가 증가하는 경우가 있을 수 있습니다.
  • ASTC의 가장 주요 기능 중 하나는 텍스처의 사용 용도에 따라 다양한 블록의 크기를 사용할 수 있다는 것입니다. (128비트 기준) 예를 들어 잠깐 등장하고 사라지는 파티클 텍스처에 대해선 파일의 크기를 더 줄일 수 있는 12x12 크기의 블록을 사용하고, 사용자가 직접 움직이는 플레이어 캐릭터 및 주요한 배경 등의 텍스처 에셋은 보다 더 좋은 퀄리티를 유지할 수 있는 4x4 크기의 블록을 사용할 수 있습니다.
  • ASTC가 위의 다른 포맷들에 비해 더 좋은 압축 효율을 보여주지만, Unity에서 기본 설정이 되지 못하는 이유는 구형 디바이스에서는 ASTC를 사용하지 못하기 때문입니다.
  • 따라서 앱의 대상 연령층, 지역, 국가에 따른 모바일 기기 분포도를 확인해 텍스처 압축 포맷을 정해야 할 수도 있습니다. 하지만 대상 모바일 기기들이 ASTC를 지원한다면 ASTC만을 사용해도 메모리 절약에 큰 도움이 될 것입니다.
  • ASTC를 지원 기준은 다음 표에서 확인할 수 있습니다.
ASTC 지원 기준

유니티에서 적용 및 성능 확인

현재 <아기상어 키즈 월드> 앱에 새롭게 추가하기 위해 작업 중인 게임 중 하나인 상어 가족 따라 쓰기로 예를 들어 성능을 확인해보겠습니다.

상어 가족 따라 쓰기에선 이전 게임들보다 더 많은 리소스들을 사용하고 있습니다. 그 중 배경 이미지는 사이즈가 커 가장 많은 메모리를 사용하는 리소스 중 하나일 것입니다. 다음 이미지는 배경 이미지를 압축하기 전으로 14.2MB라는 메모리 사용량을 보여줍니다.

압축 전 배경 이미지 메모리 사용량

유니티에서 플랫폼에 따라 텍스처 압축 포맷을 사용하는 방법은 해당 텍스처 에셋을 선택 후 Inspector 창에서 플랫폼 선택 후 Override 체크, 원하는 텍스처 사이즈, 텍스처 압축 포맷 등을 설정해주면 됩니다.

이 배경 이미지에 대해 ASTC 4x4 block을 적용한다면 메모리 사용량을 14.2MB에서 4.7MB로 기존의 3분의 1로 줄인 것을 확인할 수 있습니다.

배경 이미지에 ASTC 4x4 block 적용

추가로 Max Size를 줄인다면 메모리 사용량이 더욱더 줄어든 것을 확인할 수 있습니다

배경 이미지 Max Size 조절

텍스처 압축 포맷을 적용하기 전 텍스처 리소스가 POT인지 아닌지를 확인하는 것은 중요합니다. 이 게임에서 사용하는 배경 이미지는 NPOT(Non — POT)텍스처로 만약 PVRTC, ETC를 사용하게 된다면 오히려 메모리가 증가하는 걸 확인할 수 있습니다.

NPOT 이미지에 PVRTC 4 bits 적용

이제 게임 내 메모리 사용량을 비교해보겠습니다.따라쓰기 게임의 경우 다른 게임들보다 많은 리소스를 사용해 그만큼 더 많은 메모리를 사용하게 됩니다. (1번 이미지 — 세균 무찌르기, 2번 이미지 — 상어 가족 따라 쓰기)

세균 무찌르기
상어 가족 따라 쓰기

아래의 이미지는 상어 가족 따라 쓰기 게임에서 사용하는 텍스처 리소스들을 용도에 맞게 텍스처 압축 포맷을 적용한 후의 메모리 사용량을 보여줍니다.

텍스처 압축 적용 후 상어 가족 따라 쓰기

약 100MB 정도 메모리 사용량을 줄인 것을 확인할 수 있습니다.

이 글에선 ASTC를 적용해 테스트를 진행했지만, Unity에서 제공하는 플랫폼별 권장, 기본 및 지원 텍스처 포맷을 확인하여 가장 효율이 좋은 텍스처 압축 포맷을 사용할 수 있습니다.

마치며,

이번 글에서 확인할 수 있는 것은 텍스처 압축을 통해 생각보다 많은 메모리를 아낄 수 있다는 것입니다. <아기상어 키즈 월드> 앱에 들어가는 규모가 작은 간단한 게임들도 텍스처 압축을 통해 많은 메모리를 아낄 수 있었던 것처럼, 만약 규모가 더 큰 프로젝트를 진행한다면 텍스처 압축은 더 좋은 효과를 발휘할 수 있을 것입니다.

하지만 무작정 메모리 효율만을 생각해 압축한다면 사용자들이 보기 불편한 이미지들을 제공하게 될 것입니다. 따라서 기획자, 개발자, 디자이너 간의 의사소통을 통해 사용자들에게 보여지는 이미지의 퀄리티와 메모리 사용량을 조절해야 합니다.

따라서 텍스처 압축은 개발자만이 알아야 하는 지식이 아니라고 생각합니다. 기획자, 디자이너 또한 텍스처 압축에 대해 어느 정도의 지식이 있다면 사용자들에게 더욱 좋은 퀄리티의 게임을 제공할 수 있을 것입니다.

만약 이 글에서 잘못된 점이 있다면 좋은 지적 부탁드립니다.

긴 글 읽어주셔서 감사합니다!

참조

--

--