Unity 游戏优化

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/gohuge/article/details/82180989

 

方向(标准和性能)

有一点是我们考虑的前提,规范和标准,我们根据产品指标做出对应的数据标准,只有在这个前提下才能达到产品预期,同时只有在一套商定的标准下各个部门才能有效配合。所以我们会根据方向的几点,推导出符合自己产品定位的标准。

一、标准和规范(资源,运行指标)

资源标准衍射出加载慢,内存大,以及制作不合理问题带来的问题

所以首先我们需要制定资源规范,制定规范需考虑当前市场的手机芯片市场占用情况(芯片调查);以及该芯片在运行情况下能够达到的参数(芯片运行参数),通过这些数据结合自身游戏的特性给出资源的制作标准。当前我们也已经得到了适合自己的参数,和一些得到这些参数的途径:

1)确认游戏风格,找到参考游戏分析资源和各个机型的支持情况,确定场景运行的总面数,DrawCall次数等信息

  • 加密情况下,可以通过UnityStudio直接导出,加密的可以使用Adreno GPU Profiler得到

http://qiankanglai.me/2015/05/16/Adreno-Profiler/index.html

http://blog.csdn.net/daijy0111/article/details/50427758

  • 抓取镇魔曲分析文章实例:

https://zhuanlan.zhihu.com/p/26215257

https://zhuanlan.zhihu.com/p/27696865

2)抓取资源可能会遇到的问题(其实我们用Snapdragon Profiler没遇到下面问题)

  • 使用AdrenoProfiler首先要有一台高通芯片的手机,但也不一定能调,三星S5可以调;
  • 需要用apktools对其apk包进行解压写入允许读写标志再压包;
  • 还需要写入签名,我们先把公司的签名写进去了;
  • 包体需要是官网包,尽量不要用应用宝等渠道包,不然签名被破坏就无法安装;

3)高通有两款性能分析工具,还有一款是Snapdragon Profiler 下面给一个使用文档

https://blog.csdn.net/msf568834002/article/details/77677474

但如果要导出模型也可以采用Intel的gpa,但模型没有UV信息,下面再贴一个链接

通过调研我们除了资源规范,还得到很多数据比如(当期那市场占有率第二高通650的一些流畅保障的程序运行信息)

二、性能指标与性能测试

用的比较多的是第三方工具UWA测试的报告,GOT工具(和用户反馈),当然我们自己也会随时开启unity自带的profiler。

1、运行具体指标参考

1)UWA做了预期指标,以兼容中低端手机为目标,稳定在30帧,长时间不发热,给出了两份数据参考

2)指标要求,并给出了一些优化建议(在后面“优化建议”目录中)

  • 内存:控制在300M以下、UGUI堆内存:3M以下
  • 渲染:同屏面数不超过100K,DrawCall不超过200
  • CPU耗时:33ms以下 (1000ms/30 = 33)
  • UGUI CPU平均耗时: 5ms 以下、动画模块CPU耗时:3ms以下
  • MeshSkin.Update CPU耗时:3ms以下、粒子系统CPU耗时:3ms以下、物理模块:5ms以下
  • GC触发率:1K帧/次 以上
  • 粒子峰值数:400个以下
  • 透明贴图(粒子特效等)渲染占屏幕面积 <20%
  • ShaderMode版本:兼容2.0

三、性能影响概述(CPU/GPU/MEM)

1、CPU问题我们经常归于调度频率问题,所以原理和限制说明一下

1)GPU一般具有填充率(Fillrate)和内存带宽(Memory Bandwidth)的限制,如果你的游戏在低质量表现的情况下会快很多,那么,你很可能需要限制你在GPU的填充率。

2)CPU一般被所需要渲染物体的个数限制,CPU给GPU发送渲染物体命令叫做DrawCalls。一般来说DrawCalls数量是需要控制的,在能表现效果的前提下越少越好。通常来说,电脑平台上DrawCalls几千个之内,移动平台上DrawCalls几百个之内。

(来一个数据:高通650芯片,18年市场占有率第二,为流畅保障每帧定点<10W,DrawCalls<200)

CPU中的计算主要是在蒙皮骨骼计算,布料模拟,顶点动画,粒子模拟等。GPU则在各种顶点变换、光照、贴图混合等。

2、对GPU优化:采用高效的shader

1)需要注意的是有些(built-in)Shader是有mobile版本的,这些大大提高了顶点处理的性能。当然也会有一些限制。

2)自己写的shader请注意复杂操作符计算,类似pow,exp,log,cos,sin,tan等都是很耗时的计算,最多只用一次在每个像素点的计算。不推荐你自己写normalize,dot,inversesqart操作符,内置的肯定比你写的好。

3)需要警醒的是alpha test,这个非常耗时。

4)浮点类型运算:精度越低的浮点计算越快。

http://docs.unity3d.com/Documentation/Components/SL-ShaderPerformance.html

3、MEM内存管理,精确到分配堆栈及对象间引用关系

1)内存看起来高,因为Unity是跑在mono虚拟机上的程序,通过C#申请内存,Mono会GC程序申请的内存,但内存不会归还系统;

所以可能造成实际使用内存和程序占用内存不符的情况,解决方案(网上搜索一下各种缓存池)。

2)内存过多占用,这种通常是资源和对象管理不合理,比如资源Sharder编译多个分支部分不用的就浪费了空间,比如需要手动GC的没做到位(Combined Mesh)如下图实际使用297,但总共却又10.2k。


四、常见影响性能的模块(UI/SCENE)

1、UI(图集使用和网格重建带来的影响)使用图集、动静分离

1)引起Canvas对网格的重建大概有几种情况Image,Text等UI元素的Enable及UI元素的长、宽或Color属性的变化等。因此在一些较复杂的界面,可以多分几个Canvas出来,虽然会增加drawcall,但是减少了网格重建时间,让性能有更好的提升。

2)摇杆区,技能区,血条,经验条是比较容易变化的,把这些都放到一个叫Dynamic的节点,并有自己的canvas,这样在他们频繁变化时,也只需要对这小部分进行网格重建,相对于整个MainUI重建的开销就小非常多了。

2、场景(光照、烘焙、相机后期处理)

1)若不用光肯定是最快的。移动端优化可以采用用光照贴图(Lightmapping)去烘培一个静态的贴图,以代替每次的光照计算,在U3D中只需要非常短的时间则能生成。这个方法能大大提高效率,而且有着更好的表现效果(平滑过渡处理,还有附加阴影等)。

2)自动和并考虑和静态批处理(Batching Static网上文章较多)

3)相机后期处理,可以考虑分级处理高端机使用

4)高低模切换,远景视距模型切换,还有很多可动态调整增强性能的保障

3、高低适配

1)分辨率、高低模、阴影效果、环境光

五、开发建议

  1. 动态图集方案:《小米超神》技术总监王啸予:重度MOBA的优化之路
  2. PC平台的话保持场景中显示的顶点数少于200K~3M,移动设备的话少于10W,一切取决于你的目标GPU与CPU。
  3. 如果你用U3D自带的SHADER,在表现不差的情况下选择Mobile或Unlit目录下的。它们更高效。
  4. 尽可能共用材质。
  5. 将不需要移动的物体设为Static,让引擎可以进行其批处理。
  6. 尽可能不用灯光,动态灯光更加不要了。
  7. 尝试用压缩贴图格式,或用16位代替32位。
  8. 如果不需要别用雾效(fog)。
  9. 尝试用OcclusionCulling,在房间过道多遮挡物体多的场景非常有用。若不当反而会增加负担。
  10. 用天空盒去“褪去”远处的物体。
  11. shader中用贴图混合的方式去代替多重通道计算。
  12. shader中注意float/half/fixed的使用,shader中不要用复杂的计算pow,sin,cos,tan,log等,shader中越少Fragment越好。
  13. 注意是否有多余的动画脚本,模型自动导入到U3D会有动画脚本,大量的话会严重影响消耗CPU计算。
  14. 注意碰撞体的碰撞层,不必要的碰撞检测请舍去。
  15. 关闭贴图及网格的读写,会造成额外的内存分配。
  16. 关闭贴图的MipMap,会造成额外的内存分配(开启可以减少远处物件渲染的显存带宽压力,但是对我们的游戏帮助不大)。
  17. 关闭网格模型的读写,会造成额外的内存分配。
  18. 能动态批处理的物件就不用要静态批处理。可以考虑运行时再静态合批。
  19. 物体贴图能合图就合图,可以提高批处理率,但是要注意避免载入的贴图内存量。
  20. 资源有用时才加载,没用就卸载,来减少内存占用,但是要注意频繁的加载卸载资源会造成额外的GC。
  21. 显示全屏UI,不需要看到场景时,可以关闭场景相机的渲染。
  22. 避免频繁实例化与删除物体,激活及关闭物体。
  23. 字符串是在内存里是不可修改的,每次修改都会分配新内存。减少对字符串的操作次数或操作的字符数,或使用StringBuilder。
  24. 减少Debug.Log()输出。
  25. 使用缓存变量来避免频繁的内存分配。
  26. 不需要每帧执行的逻辑就优化轮询,按刻处理。
  27. 不要使用多个相机做设计。

猜你喜欢

转载自blog.csdn.net/gohuge/article/details/82180989