腾讯是如何做Unity手游性能优化的
他山之石—腾讯是如何做Unity手游性能优化的
本文转载自:http://www.taidous.com/thread-44045-1-1.html?_dsign=ba1258b9
俗话说,用户体验不谈性能就是耍流氓。 在PC游戏上的性能问题并没有那么明显,加个内存换个CPU或者刷个主频就能轻松搞定;到了手游时代后情况则显得比较严峻,捉襟见肘的内存使得资源加载时如履薄冰,加上高中低不同配置的机型让性能问题显得更加突出,一个低端机型上的卡顿就可能造成一大批屌丝用户的流失,这当然无法被忽视。 在手游的浪潮之巅,腾讯对于手游品质的要求从1.0到2.0再到现在的3.0,不仅是玩法和内容,在游戏质量的审核上也始终如一的保持着高要求高标准。腾讯游戏的品质管理中心在Unity手游性能上进行了更深层次的挖掘,这是一个腾讯内部非常受欢迎的性能分析产品,无论你是否正在从事Unity相关的工作,听完这个良心产品的故事保证会让你增加90%的魅力值。但在此之前、先要看看你的“性”能到底行不行? (下文有大量专业术语,有可能引起您的不适,请在家长指导下阅读。) 一.常见的Unity手游性能问题有哪些? Unity手游的性能问题一直是被业内视为诟病,腾讯公司内部的TDR评审就是一个专门针对技术细节进行专家团评估的环节;早期的TDR评审关注的是内存是否超标、CPU是否饱和、网络流量是否过大等数据,经过近几年手游浪潮的洗礼,现在评审过程中会更加注重细分问题的研究和排查。如果说左边是玩家经常会遭遇到的表面现象,那右边则是基于Unity引擎深挖后的问题本质。 它们对游戏的具体影响是什么呢?就拿最近比较火的《王者荣耀》来举例,我们有幸参与了它上线前后的几个优化版本的分析,先后遇到过的问题和优化方法主要有下面几个:
通过Cube的深度分析,能够帮助开发者发现当前游戏内分类资源的占用情况。
如上图所示,在资源分析纬度上可以给出如下结论:· 资源使用总量是否在合理范围之内。· 一个场景内的资源重复率。· 资源对象拷贝的数量是否合理。· 场景切换时保留的资源详情。· 网格、纹理、音频、动画、GameObject等资源是否超标。 在性能分析纬度上,以腾讯的TDR标准为例,在高中低三档机型上会有不同的标准,Cube在三档机型中做了自动的筛选和判定,便于开发人员能更加直观的发现问题。(如下图)
所以答案是肯定的,日常测试工作中加入了数据采集和数据分析功能,就可以提高很大的工作效率。 我们常见的产品质量改进流程无非是下面这四步: 1) 测试人员发现问题; 2) 提bug 给开发人员; 3) 开发人员编译develop版本; 4) 开发人员用Unity profiler 定位原因; 用Cube进行游戏测试能帮你省掉后面2个步骤,何乐而不为呢?通常情况下,开发人员是间隔几个星期甚至几个月才会去做一次性能调优的工作,中间已经隔了N个版本,有很多问题会被埋的很深;基于“问题发现的越早修复成本越小”的硬道理,功能测试人员完全可以用Cube进行日常的版本功能测试,让Cube在后台默默的为你发现各种性能问题。 l 即插即用、无须编译无须嵌入SDK、真机运行数据; l 提供mono内存分配信息和mono快照对比; l 能看到整个测试流程中的所有数据,而不仅仅是某一段时间; l 被误操作产生的对象拷贝数量; l 函数开销排名; l 关卡间保留的冗余资源; 五.性能优化的N种武器作为一个以性能优化为己任的工具类产品,Cube不仅致力于问题的发现和定位,也希望为开发人员提供更多更实用的性能优化方法。 贴图: l 控制贴图大小,尽量不要超过 1024 x1024; l 尽量使用2的n次幂大小的贴图,否则GfxDriver里会有2份贴图; l 尽量使用压缩格式减小贴图大小; l 若干种贴图合并技术; l 去除多余的alpha通道; l 不同设备使用不同的纹理贴图,分层显示; 模型: l 尽量控制模型的面数,小于1500会比较合适; l 不同设备使用不同的模型面数; l 尽量保持在30根骨骼内; l 一个网格不要超过3个material; 动画: l N种动画压缩方法; l 尽量减少骨骼数量; 声音: l 采用压缩MP3 和 wav;资源方面的优化: l 使用 Resource.Load 方法在需要的时候再读取资源; l 各种资源在使用完成后,尽快用Resource.UnloadAsset和UnloadUnusedAsset卸载掉; l 灵活运用AssetBundle的Load和Unload方法动态加载资源,避免主要场景内的初始化内存占用过高;(实现起来真的很难…) l 采用www加载了AssetBundle后,要用www.Dispose 及时释放; l 在关卡内谨慎使用DontDestroyOnLoad,被标注的资源会常驻内存; 代码的优化: l 尽量避免代码中的任何字符串连接,因为这会给GC带来太多垃圾; l 用简单的“for”循环代替“foreach”循环; l 为所有游戏内的动态物体使用内存对象池,可以减少系统开销和内存碎片,复用对象实例,构建自己的内存管理模式,减少Instantiate和Destory; l 尽量不使用LINQ命令,因为它们一般会分配中间缓器,而这很容易生成垃圾内存; l 将引用本地缓存到元件中会减少每次在一个游戏对象中使用 “GetComponent” 获取一个元件引用的需求; l 减少角色控制器移动命令的调用。移动角色控制器会同步发生,每次调用都会耗损较大的性能; l 最小化碰撞检测请求(例如ray casts和sphere checks),尽量从每次检查中获得更多信息; l AI逻辑通常会生成大量物理查询,建议让AI更新循环设置低于图像更新循环,以减少CPU负荷; l 要尽量减少Unity回调函数,哪怕是空函数也不要留着;(例如空的Update、FixedUpdate函数) l 尽量少使用FindObjectsOfType函数,这个函数非常慢,尽量少用且一定不要在Update里调用; l 千万一定要控制mono堆内存的大小; 六.小结 性能优化就像海绵中的水,又或是内衣里的肉,挤一挤总会有的。同时,性能优化并不是一劳永逸的工作,而是一个漫长而具有挑战的任务;项目的各个阶段都会有性能上的问题,在用户体验的基础上持续进行打磨,持续保持产品的良好性能才能赢得好口碑。(和保持身体健康是一个道理)
Unity手游的性能优化过程更像是一门时空转换的艺术, 持续在CPU和内存之间取得一个平衡。空间不足时则需要释放一些无用数据,以获得更优的空间使用率;时间太长时就需要降低不必要的函数开销。例如在低端机上,为了节约有限的内存空间,静态加载的资源会相对较少,很大一部分资源通过动态加载和释放;而在高端机上则不用考虑空间的限制,可以一次性静态加载更多的资源,省去了不少loading和GC的工作,让游戏体验更加流畅。
本文由腾讯WeTest授权发布 作者:chunhe,腾讯资深后台开发工程师。 链接:http://wetest.qq.com/lab/view/108.html 著作权归作者所有。商业转载请联系WeTest获得授权,非商业转载请注明出处。
声明:该文观点仅代表作者本人,牛骨文系教育信息发布平台,牛骨文仅提供信息存储空间服务。
- 上一篇: 区块链技术(一):Truffle开发入门
- 下一篇: 如何进行简单的区块链编程,也许LISK是个选项