耗电量与发热量优化
检测前需要确保手机电池健康,这会直接影响测试结果
温度墙与降频
现代手机芯片和硬件都会设定一个温度临界值,超过就会调度芯片降频,直接表现就是掉帧。优化的主要目的是推迟触发温度墙的时间,以及降低触发降频的持续时间。
温度升高的原因如下图,其中开发者需要关注:
- CPU负载
- GPU负载
- 网络通讯
- IO方面
常规优化
可视游戏品类适当放开,若在该标准下几乎是不会触发温度墙。不要让GPU、CPU一直处于满负载运行,要有充分的休息时间。GPU带来的发热量一般比CPU要大,CPU可以适当放开。
- 60fps -> CPU 10-12ms,GPU 6-8ms
- 30fps -> CPU 18-20ms,GPU 8-10ms
非常规优化
- 网络与io
- 发包频率
- 频繁io读写
- 显示亮度与FPS
- 省电模式
- OnDemandRendering
- UI显示、待机时主动降显示频率
- 动态分辦率
- 降低屏幕亮度
- 三方库
- Wwise/Criware(这两个开销都很高)
- 平台SDK,看看有没有提供优化设置接口,裸包与平台包发热测试
启动时间优化
- 启动黑屏到Unity Logo图标出现的阶段
- Unity Logo出现到进入第一个场景后的阶段
iOS平台启动时间优化
iOS平台Unity程序启动流程
iOS平台程序启动需要注意的点
1.不同版本的iOS系统程序启动时问略有差异
2. iOS启动分为首次启动,冷启动与热启动,一般我们所说的优化是指冷启动
3. 启动时间超过20秒的程序会被系统自动杀掉
4. 默认竖屏程序比横屏程序启动时间略长
5. 推荐Pre main时间最好不要超过400ms
6. 测试iOS Pre main过程的方法,iOS14及以前的版本,开启DYLD_PRINT_ STATISTICS或DYLD_PRINT_STATISTICS_DETAIL
7. iOS15以后Xcode Timeline查看整体启动过程
iOS PRE MAIN阶段优化建议
1.文件瘦身,合并重复或删除用不到的一些代码,这里我们可以通过Strip Engine Code来减少Unity
引擎库的大小,但一些第三方库可以通过APPCode检测当前没有用的类和代码并剔除。
2. 减少不必要的Framework与引用的动态链接库加载
3. 使用Static Archives链接dyLib
4. C++代码中减少全局静态变量的使用,以及过度抽象,注意虚函数表的开销(10000+)
5. OC对象将在+load方法中要做的事延迟到+initialize方法中
6. 减少OC对象的metadata
7. 在initializers中尽量不要调用dlopen,不要创建线程
8. 注意一些三方库与平台SDK
Android平台启动时间优化
Android平台Unity程序启动流程
Android平台程序启动需要注意的点
1.不同版本的Android系统程序启动时间略有差异
2. Android启动分为首次启动,冷启动与热启动,一般我们所说的优化是指冷启动
3. App进入后台可能会被系统自动杀掉,恢复也算冷启动
4. Unity中Activity的android:launchMode属性一定要保证是SingleTask的,否则原生界面调出,或切
到后台等都可能发生崩溃
5. 通过adb logcat查看日志中Displayed标签来查看程序启动到显示前时间
6,通过Android Studio 的Android CPU profiler工具来定位启动时瓶颈
7. 使用GooglePlay的Android vitals来发现启动异常问题
8. 一些三方库与平台SDK对启动时间的影响
Android 启动优化建议
1.减少Activity onCreate函数中复杂的逻辑工作
2. 将所有的资源初始化做Lazy Load放到不同的线程中,不要全部放到主线程中
UNITY初始化完成到第一个场景加载完成优化建议
- 尽量不要使用Resources目录,即使使用也不要有过多资源,因为其会在运行时构建索引
- 第一个场景尽量保持简单,挂载脚本不宜过多,Awake/Start的逻辑尽量简单
- 资源Tex模式比force binary模式慢很多
- Graphics下Always Include下不宜包含太多或太复杂的Shader脚本。
- 要做Shader变体剔除,变体过多的项目不要使用Shader.WarmupAllShaders来做ShaderCache
- ab包不宜打的过碎,尽量使用LZ4压缩,不要使用LZMA压缩
- 另外注意编辑器下一些InitializeOnLoad, InitializeOnLoadMethod属性,运行时RuntimeInitializeOnLoadMethod等属性标记的函数如果过于复杂也会影响编辑器启动与Player启动的速度。
打包优化
- 减少资源包大小与冷启动速度
- AB包打包优化
- BuildPipeline + 自行开发工具/AssetGraph
- Unity Scriptable Build Pipeline + Addressables
AssetBundle
- AssetBundle是一个存档文件,包含运行时加载的特定平合的非代码资源,与彼此之间的依赖关系
- AssetBundle可以用于资源更新,减少安装大小,针对平合加载优化资源,减轻运行时内存压力
- AssetBundle是一个容器,包含存档文件包头、以及序列化类型文件与资源文件
构建AssetBundle参考策略
- 根据对象的修改频率差异拆分不同的AssetBundle
- 具有相同生命周期的资源打成一个AssetBundle,如果一个AB中只有不到50%的资源
经常加载,可以考虑拆到不同的AssetBundle中 - 不可能同时加载的高低配置资源拆分到不同的AssetBundle
- 如果多个对象依赖于某个AssetBundle中的单个资源,这类单个资源可以单独打包或者根据生命周期将这头被多个对象依赖的资源打成共享AssetBundle
- 如果一组对象只是一个对象的不同版本,可以考虑使用AB变体(注意Addressable不支持AB变体)
构建AssetBundle值得注意的点
- AB包体不能因为避免重复引用,拆的过于细碎,2M-5M的包体是一个合理的参考值。过小的包体,包头占用内存压力会比较大,资源加载与销毁反复创建销毁文件句柄会造成系统资源开销大,电量消耗加大
- LZMA格式压缩的AB包较小,但需要完全解压后再加载,加载时问更长,LZ4格式压缩的AB包按块加载.加载时间较快,但包体大小较大,移动平台建议使用LZ4压缩格式。
- 如果确定使用相同版本Unity发布打包,后续开发不会升级Unity版本,AB包体不做Unity版本兼容时可以尝试开启打包选项BuildAssetBundleOption.DisableWriteTypeTree选项,这样TypeTree信息不会被打到AB中,可以极大减小包体大小区运行加载时的内存开销
- 避免同一个资源被打入多个AB中,会增加运行时内存开销,可以使用UPR AssetsChecker工具来做检查。小心Unity内置资源被重复打入多个包,应尽量使用自定义资源替换(如默认粒子的创建)
- 不要使用AB包文件的MD5值作为更新包依据,可能存在包内资源没变化但生成包md5发生变化(包内资源和路径变化)