简介
苹果对于IOS执行档的大小是有明确的限制的,其中TEXT段的大小不能超过80M,否则提审将会被苹果拒绝,同时,如果TEXT段过于太大,那么在苹果进行加密之后,很容易出现解压失败等各种异常,最终导致游戏无法正常运行。因此,理论上我们应该尽可能保持我们的执行档TEXT段大小小于80M,根据经验,始终保持在60-70M以下是相对比较保险的。请注意,这里说的80M是包含armv7和arm64两种架构的执行档的TEXT段之和而并非单个架构,即单个架构的TEXT段大小不能超过40M。
IOS的执行档格式为mach-o格式,关于这种个是可以看苹果的文档或者维基百科。另外有工具Mach-o Viewer可以帮助你检阅这些信息。
查看TEXT段大小的方法
首先简单介绍查看执行档TEXT段大小的方法。在Mac系统下,使用XCode生成项目之后,生成的执行档都在DerivedData目录下,这个目录可以使用Command + Shift + G跳转过去,目标地址:
~/资源库/Developer/Xcode/DerivedData/
可以简单通过子目录的时间戳分析出最近的生成位于哪个目录下,依次向前即可找到生成的执行档,这是一个包。查看包内容,里面会有一个同名的可执行文件,此文件可以等效于Windows下面的exe文件。可以将其复制到桌面或者其它地方,也可以不复制。打开终端,进入对应目录。使用命令size即可显示执行档的各段的大小数据,如:
Bodong-iMac:Documents bodong$ size ./xxgame
__TEXT __DATA __OBJC others dec hex
34373632 10518528 0 2179072 47071232 2ce4000 ./xxgame (for architecture armv7)
39534592 17203200 0 4296835072 4353572864 1037e4000 ./xxgame (for architecture arm64)
上面加粗的数据即是TEXT段的大小,最终的TEXT段的大小为两种架构大小之和。倘若它们之和大于80M,你的执行档可能会被苹果拒绝。
为什么要强调Unity
如果我们直接使用C++开发,一般来说并不会有关于TEXT段太大的问题,然而Unity不一样,Unity使用的mono C#开发,在build时通过il2cpp将C#代码编译结果翻译成C++代码,由于il2cpp翻译的C++代码需要模拟很多C#的行为,因此它本身生成的代码量会远远高于实现这些功能所需要的C++代码数量。代码体积巨大的结果就是TEXT段大小会超标,这样会对游戏发布产生巨大的影响。
这里我选择了我自己的一个非常简单的项目来做实例进行展示,代码很少,因此并不会造成TEXT段过大的问题,但是当你的项目足够大时,就会有问题了。这里用于展示,原理是一样的。
Unity对IOS生成的结果是一个Xcode项目。其中在Classes/Native下面,就是我们生成的代码,如果这个文件夹的总大小超过了300M,那请注意,你的执行档TEXT段可能就要超标了。因此大多数的优化目的都是为了减小这个Native文件夹的总大小,根据经验,这里减少5m左右,执行档TEXT段就可以减少1m。
具体技术细节
有很多方法可以减少Native文件夹的大小,这里依依列出。另外部分优化的具体数据由于时间问题已经记不清了,只能记得大概的数据。
1.一定使用Release编译,一定使用非Development Build。
2.项目Build Player Setting中,Api Compatibility Level一定要采用.net 2.0 subset。可减少数M。
3.strip一定要开,unity4里面选择strip level选择strip by byte code,选择micro mscorlib可能会导致crash,可以先不考虑;unity5中勾上strip Engine Code。可减少数M。
4.移除非必须使用的.net基础库,比如System.xml,可以使用其它更精简的库代替。比如System.xml的替代者SecurityParser。移除这个大模块后,可减少TEXT段3-5M。同理,System.Linq也应该尽量不用,其一是容量问题,其二是效率问题,其三是在iphone4s下面可能导致crash的问题。
5.少用或不用模板。在早期的unity版本(4.6.6之前),尤为甚之。模板会导致代码量剧烈膨胀,要查看自己的模板代码总共贡献了多少C++代码,可以在native文件夹中搜搜Generic,其中有大部分C++代码就是模板的贡献。
倘若你的模板生成的C++代码总数量大于了40m,那你应该提高警惕。造成这些暴涨的主要元凶就是System.Collection.Generic下面的各种容器,比如List,Dictionary,其解决方案就是针对class类型的类型衰减。我已经提供了新的ListView和DictionaryView,DictionaryObjectView容器,它们不会导致模板生成代码暴涨。相关代码可以在我的一个开源项目CheatConsole中找到,地址:https://github.com/sczybt/CheatConsole 。
6.统一使用C#,不要使用javascript或者boo,哪怕只有一个javascript或者boo代码文件,都会导致Unity引用两个你根本不需要的库Unity.Lang和Boo.Lang。这个可以通过在Native文件夹下面搜索名字包含Lang的C++文件来验证。这个要求也包括第三方库,如果第三库中有这些代码,也会产生问题。
7.移除不再使用的代码。比如一些三方库的Example代码,永远用不到的组件等等。
8.尽量升级到新版本的Unity,一般来说新版本较旧版本都会在这方面做一些优化。比如4.6.6相比4.6.5就优化了大约30%以上的生成代码容量。
总结
使用了如上策略之后,我们项目的执行档大小从最初的300m减小到90m,TEXT段大小从190M减小到70M。大家可以对这些方法进行验证,并提前做好预防工作。