iOS 플레이어(Player) 빌드 사이즈

유니티iOS에 의해 빌드되는 플레이어의 사이즈를 줄이는 방법은 두 가지 입니다:

  1. Xcode 안에서 Active Build Configuration을 바꾸는 것과
  2. Unity iOS 에서 Stripping Level을 바꾸는것입니다.

배포상태의 빌딩

Xcode 프로젝트 폴더를 빌딩 한 후, the Active Build Configuration 드롭 다운 메뉴에서 Debug 또는 Release를 선택 할 수 있습니다. Debug 대신 Release로 빌딩을 하면, 게임에 따라 플레이어의 사이즈는 2-3MB로 줄어듭니다.


Active Build 설정(Configuration) 드롭 다운 메뉴

배포로 빌딩 했을 때는 플레이어로부터 디버그 정보가 빠집니다. 그러므로, 게임이 충돌하거나, 다른 문제가 있으면, 스택을 추적할 아웃풋이 없습니다. 이 경우는, 디버그 버전으로 게임을 빌드 하시면 충돌을 재생하여 완전한 디버그 정보를 얻을 수 있습니다.

iOS Stripping 단계 (고급 라이센스 기능)

Stripping관련 크기 최적화는 다음과 같이 작동합니다:

A) Strip assemblies level: script 바이트 코드는 분석됩니다. 스크립트로부터 참조되지 않은 클래스들과 함수들은 DLL에서 제거되고, AOT 스텝으로부터 제외됩니다. 이러한 최적화는 주요 바이너리와 동반하는 DLL 크기를 감소시킵니다. 이 기능은 반사가 사용되지 않을 때 안전합니다.

B) Strip ByteCode level: 동반되는 .NET DLLs (Data 폴더에 저장된)은 메타데이터 까지만 strip 됩니다. 이는 모든 코드가 AOT로 미리 컴파일되어 메인 라이브러리로 링크가 되어서 가능합니다.

C) Use micro mscorlib level: 특별한, 작은 버전의mscorlib이 사용됩니다. 몇몇 컴포넌트들은 이 라이브러리로부터 제거됩니다. 예를 들어, Security, Reflection.Emit, Remoting, non Gregorian calendars등이 제거됩니다. 또한, 내부 컴포넌트의 상호 의존도가 최소화 됩니다. 이러한 최적화는 메인 바이너리와mscorlib.dll의 크기를 줄입니다. 이 기능은 몇몇 System 과 System.Xml 어셈블리 클래스들에게는 호환되지 않습니다. 그러므로 주의 깊게 사용하십시오.

_메모:_ 이러한 레벨들은 축적됩니다. 그러므로, 레벨 (C) 최적화는 레벨 (B) 와 레벨 (A) 최적화를 포함하며, 레벨 (B) 최적화는 레벨 (A) 최적화를 포함합니다.

_메모:_ 마이크로 mscorlib는 핵심 라이브러리의 스트립트된 버전입니다. 유니티 엔진에서 모노 실행시 필요한 아이템들을 그대로 남습니다. 마이크로mscorlib를 사용하는 가장 좋은 습관은 어플리케이션에 필요하지 않는 .NET의 클래스/기능들을 사용하지 않는 것입니다. GUID는 사용되지 말아야 할 좋은 예입니다. 이들은 사용자 제작의 pseudo GUIDs로 쉽게 대체됩니다. 그리고 더 좋은 성능과 어플리케이션 크기를 제공합니다.

Tips

반사가 사용될 때 스트리핑(stripping)을 다루는 법

스트리핑은 정적 코드 분석에 많이 의존하며, 작업을 올바로 실행하는데 실패합니다. 특히, 동적인 기능들(반사와 같은)이 사용 되었을 때입니다. 그러한 경우, 어떤 클래스들을 접근하지 말아야 하는지의 힌트들이 필요합니다. Unity iOS는 사용자 스트리핑 black list를 지원합니다. 그 과정은 간단합니다:

1. link.xml 파일을 생성하고, 이를 Assets (project root) 폴더에 직접 위치 시킵니다. 2. link.xml의 구조의 예는 다음과 같습니다:

<linker>
       <assembly fullname="System.Web.Services">
               <type fullname="System.Web.Services.Protocols.SoapTypeStubInfo" preserve="all"/>
               <type fullname="System.Web.Services.Configuration.WebServicesConfigurationSectionHandler" preserve="all"/>
       </assembly>
 
       <assembly fullname="System">
               <type fullname="System.Net.Configuration.WebRequestModuleHandler" preserve="all"/>
               <type fullname="System.Net.HttpRequestCreator" preserve="all"/>
               <type fullname="System.Net.FileWebRequestCreator" preserve="all"/>
       </assembly>
</linker>

_메모:_ 때로는 어떤 코드들이 스트립 되어야 하는지 확인하는 것은 문제가 있을 수 있습니다. 그러나, 어플리케이션이 동작하려면 여전히 필요합니다. 시뮬레이터에서 스트립된 어플리케이션을 실행하고 Xcode 콘솔에서 에러메시지들을 보는 것으로 약간의 힌트들을 얻을 수 있습니다.

배포를 가능한 최소화 시키는 간단한 체크리스트

  1. asset들을 최소화 합니다: 모든 질감PVRTC를 압축하며, 질감의 해상도를 가능한 줄입니다. 압축되지 않는 사운드들은 최소화 홥니다. 파일크기 줄이기 문서는 here에 있습니다.
  2. iOS 사용할 스트리핑 레벨을 Use micro mscorlib로 설정합니다.
  3. 스크립트 호출 최적화를 Fast but no exceptions로 설정합니다.
  4. 코드 안에서 System.dll 이나 System.Xml.dll 에 상주하는 코드를 사용하지 않습니다. 이들은 micro mscorlib와 호환되_지 않_습니다.
  5. 불필요한 코드들의 상호관계를 제거 합니다.
  6. 불필요한asset들을 제거 합니다.
  7. .Net 2.0 subset을 Api 호환 레벨로 사용합니다. .Net 2.0서브셋은 다른 라이브러리들과 제한된 호환성을 가집니다.
  8. 타겟 플랫폼을 armv6 (OpenGL ES1.1)로 설정하십시오.
  9. JS Arrays를 사용하지 마십시오.
  10. generic 컨테이너와 value types을 함께 사용하지 마십시오 (모든 구조체는 value type입니다).

Unity iOS 로 20메가 바이트 아래로 가능한가요?

네, 빈(empty) 프로젝트는 모든 최적화 레벨을 끈 상태로 AppStore 에서 ~13 MB 이내로 가능합니다. 게임에서 압축된 asset을 위한 아직 ~7MB 의 여유공간이 있습니다. 만약 고급 라이선스(스트리핑 옵션을 위해 필요함)를 가지고 계시면, 훨씬 더 좋습니다. 이 경우는 주요 카메라와 빈 장면으로 AppStore(zip으로 압축하고DRM 부착)에서 6MB 공간만 필요합니다. 이 경우 압축된 asset을 위한 아직 ~14MB 의 여유공간이 있습니다.

나의 어플리케이션이 AppStore로 배포되었을 때 사이즈가 늘어났습니다. 어떻게 사이즈가 늘어나는 것을 막을 수 있을까요?

AppStore에 배포되었을 때, Apple은 우선 바이너리 파일을 암호화 하고, 그것을 zip으로 압축합니다. 종종, Apple의 DRM은 바이너리 크기를 4MB 정도 증가 시킵니다. 일반적인 룰로는, 마지막 크기를 다음과 같이 예측합니다: 실행파일을 제외한 모든 파일들의 압축 사이즈 + 압축되지 않는 실행파일의 사이즈. 배포파일을 최대한 작게 만드는 방법은 위의 리스트를 참조하십시오.

역링크