优化与调试的工具
讲到优化,嘉宾们几乎都会提到优化与调试工具,掌握工具是性能优化的基础。那么都有哪些工具呢?常用的有三个:
第一是性能统计工具,这是LayaAir引擎内置的性能统计工具,在代码加入
Laya.Stat.show();
引擎内置的性能统计工具
打开这个工具后,可以用于观察性能,除了FPS越高越好外,其它的值越低越好。这里尤其要关注DrawCall数量,这是重要的优化指标,尽量要控制在100以下。
第二是DebugPanel调试工具,这也是LayaAir引擎自带的调试工具,类似DIV调试窗口,可审查页面中的各个子元素,通过查看与修改元素属性,以及查看重绘区,可以方便项目的优化与调试。在初始化舞台后通过DebugPanel.init();开启。(具体使用方式可查看Layabox官网文档的详细说明。)
DebugPanel调试工具
第三是Chrome性能分析器,Chrome是H5游戏常用的开发与调试环境,其中的性能分析器Profiles是游戏开发者很重要的优化工具之一,通常用于分析检查内存与CPU的占用。从而进行针对性的优化。(Layabox官网文档有详细使用说明)
Chrome性能分析器Profiles
优化:减少DrawCall
1、避免交叉渲染
要减少DrawCall,首先要了解底层的渲染原理。相邻相同的图集在渲染的时候会自动合并,这样就可以减少DrawCall。所以我们要注意,尽量要保证图集的图片渲染顺序是挨着的,如果是交叉渲染,那就会增加DrawCall。
那如何改变图片的渲染顺序呢?LayaAirIDE的UI编辑器其实就自带UI界面的优化功能,我们打开UI编辑器的层级管理器,可以直观的看出每一个图片资源的层级关系。并且会通过不同颜色的圆点进行区分。如果相同颜色的圆点被交叉打断,那就会增加DrawCall数量,所以,要通过调整层次关系,让相同颜色圆点的资源顺序排列。
通过LayaAirIDE的UI编辑器优化DrawCall
除此之外,要尽量保证同一个面板中的所有资源用一个图集,这样就能减少提交的批次。
2、复用3D材质
3D游戏的DrawCall数量主要是受材质的影响,同屏材质数量越多DrawCall数越多。所以尽量复用材质,LayaAir引擎会对复用的材质进行合并优化,所以DrawCall数量会相对的减少。
3、控制常用模型的面数
LayaAir引擎会对20个面以下的相同模型,自动动态合并,例如,特效和子弹等。所以在美术制作资源的时候,要对美术提出要求,对反复使用的模型尽量控制面数。
4、静态场景的优化方法
对于材质相同的静态场景,LayaAir引擎提供了静态合并方法StaticBatchManager.combine(),使用后可以大量减少DrawCall数量。
优化:减少Sprite
1、减少层次嵌套
尽量减少不必要的层次嵌套,就可以减少Sprite数量。
2、非可见区域的处理
在非可见区域的对象尽量要从显示列表移除,或者将对象设置visible = false。如果不设置,就会遍历全部的显示对象节点。存在大量的对象时,就会导致性能降低。
3、设置cacheAs属性
对于容器内有大量静态内容或者不经常变化的内容(比如按钮),可以对整个容器设置cacheAs属性,这样就可以大量减少Sprite的数量,显著的提高性能。如果有动态内容,最好和静态内容分开,以便只缓存静态内容。
4、3D模型数量控制
3D游戏的性能优化,不仅是程序的工作,美术也要有严格的制作标准。比如在美术制作资源的时候,不影响效果与功能需求的前提下,尽量合并模型减少数量,可减少Sprite数量,减少引擎渲染时的遍历节点时间。
5、摄像机裁剪优化
对于大型的3D场景来说,模型的面数与材质非常多,但是远处的部分几乎是看不清楚,这时可以采用摄像机裁剪功能,将远处看不清的模型与材质不渲染,结合场景雾效的话,并不影响美术效果,却可以减少Sprite与DrawCall的数量。
优化:减少CPU消耗
通过Chrome性能分析器,我们可以查看到CPU的消耗,如何减少呢,也是多位嘉宾提到。这里重点整理一下大天使主程陈策分享的优化经验。
1、减少A星寻路的调用
A星寻路在游戏中比较常用,但是某些情况下,可以用其它方式解决的,尽量不要使用A星寻路。我们先来对比一下。
假设在一个5*12的格子区域内,通常从对角A点到B点,如果用A星算法,需要计算很多区域,如上图的蓝色格子部分。
如果只判断长和宽这些点里的每个点是否可以移动,那就可以判断是否可以直线过去了。下图蓝色格子是需要计算的区域,这样对比起来,明显要比A星少很多。
所以,判断两个点之间是否可以直线移过去,如果可以,就不要使用A星寻路,这样就可以减少CPU运算。
2、在每一帧里进行运算
通常挂机玩法的战斗,大部分是需要客户端来运算的。运算之后再由服务端验证。比如,与一个怪物的战斗会面临是否命中、是否暴击、是否无敌等等很多属性计算,然而游戏中大多数都不是一个一个的怪物出来和你打,经常是要的多个。尤其是有一个玩法里,怪物会越来越多。如果怪物累加到100个,就视为失败。如果我们每次攻击都要计算100次怪物的状态,那就会比较消耗性能。
那怎么做可以降低消耗呢?把所有的目标(怪)放到一个列表里,根据玩法的不同,每一帧取出不同数量的怪。比如,怪物不多的时候取一两个,怪物多的时候取十个,剩下的怪在下一帧里再运算。随然显示效果会有所延迟,但是伤害等数值的飘出等效果,因为不是同时出来,反而会显的更自然。最关键的是,CPU消耗会得到降低。
3、服务端推数据引发的运算技巧
比如,客户端收到服务端发来的大量信息,然后解析数据通知到相应模块的controller,再到更新数据层,刷新界面显示。有可能会在界面上添加或删除各种显示对象等等操作,每当服务端推数据过来,如果引发大量的运算,这时在进行一次性运算就会卡住。
LayaAir里有一个方法,可以得到从这一帧的帧头到目前经过了多少时间,如果经过的时间每达到一帧的正常时间,那就开始处理服务端的数据。虽然运算时间不会缩减,但是没有造成卡住的现象。
4、分阶段处理复杂界面
在游戏中会有大量复杂的界面,比如背包,当背包的数据很多的时候,如果第一次打开,就会创建大量的子对象,在创建大量对象的时候可能会卡,这时候界面可以按处理服务端数据一样,按每一帧的时间分阶段处理。这样背包打开的时候,就会感觉到界面上的子元素是一个个的出来,没有了卡顿现象。
5、对象池的使用
每次创建对象都会消耗CPU,所以使用对象池就可以避免大量对象的创建。如果我们每次对象使用完了都放到池子里,比如怪物,子弹等等,怪物被杀死了,不需要用了,就可以放到池子里,下次使用的时候可以直接从池子里拿,对象池没有才需要创建。
但是需要注意的是,对象池能不能随便用,通常用于经常重复使用和回收的对象,比如:怪、怪杀死后的经验球、杀怪掉落的道具、技能效果、飘字、地图分块等等。
6、限制技能特效与飘字的数量
如果我们不限制飘字和特效的数量,不仅是效果根本看不清,更容易造成大量的CPU消耗,因此,限制技能特效与飘字等效果的创建和显示数量,也是优化CPU消耗的策略之一。
优化:减少内存占用
内存也是游戏里非常重要的优化指标,在手机里通常留给游戏的并不多,尤其是iOS系统,对内存的控制更加严格,如果内存占用过大,就可能会导致游戏的崩溃。这也是每个嘉宾都会提及的优化重心。如何查看内存占用,就不在这里介绍了,欢迎前往Layabox官网文档中查看。这里重点整理一下嘉宾们分享的优化要点。
1、资源的释放
使用对象池不仅可以优化CPU,还可以减少对象创建时的内存消耗。所以,无论是2D项目还是3D项目,对于经常重复使用的对象都要适当的使用对象池。
对于不用的资源,我们一定要释放掉。但是如果一会还需要用,那就不要轻易释放。因为释放后重新加载也会消耗性能。所以要根据不同的资源和策略进行权衡。
比如说UI资源,当玩家打开之后,一定时间之内没有再次打开。那么就可以检查一下这个UI的资源没有被其它地方所使用,如果没有,那就可以移除掉。
如果UI上有动画,那么当UI界面被关闭的时候,没有其它界面在使用这个动画,也可以立即删除这个动画。
像角色、技能动画、声音等,也都是和UI一样,一定时间之内没有再次使用,就可以检查是否在其它地方使用,如果没有,就可以立即删除。
如果游戏里需要切换地图,那么地图上掉落的道具等,都可以立即删除。
需要注意的是显示对象的内存清空可以使用destory()方法。该方法会真正从内存中释放并设置为null,但他并不清空显示对象所用到的资源。
而释放资源有三种,分别是手动释放的方法clearRes()与clearTextureRes(),以及在资源管理器ResourceManager中将autoRelease=true,实现自动释放。
如果项目较大,建议不要采用自动释放功能。因为这个功能只有在超出内存上限的时候,才会释放资源。并且被自动释放后,如果释放的资源还在被其它地方使用,那么有可能还会出现一边清一边用。造成闪屏的现象。
手动释放的方法里,推荐使用clearTextureRes()方法。这是当前的最新版本LayaAir 1.7.12里新增的方法。
与以前的clearRes()相比,clearTextureRes()方法只销毁了texture使用的图片资源,但会保留texture资源壳,在下次渲染的时候,发现texture使用的图片资源不存在,则会自动恢复图片资源用于显示。而clearRes会彻底销毁texture,导致不能再使用。另外,clearTextureRes()能确保立即销毁图片资源,不用担心销毁失败。而clearRes()则采用引用计数方式销毁,如果其他地方有资源引用,则资源无法被销毁。
提示:如果是大图合集,无论是clearRes()还是clearTextureRes(),都无法销毁。如果想手动管理的资源,可以关闭自动大图合集的功能,或改变大图合集的规则。
如果是3D资源需要释放,只能是手动管理,使用despose()方法将资源从显存中移除。如果积累太多资源没有释放,可能会引起崩溃,所以开发者需要有随时将不用的资源移除的习惯。
2、图集的制作规则
比如上图这个按钮,原来的设计是138*305,由于显存里会自动把宽高填充到2的整数幂。所以在显存里就变成了256*512。如果进行等比缩放,把尺寸改为116*256,那么显存里就只有128*256。内存就减少到原来的4分之1。
3、不在显示区域里的对象不加载
通常RPG类型的游戏,整个地图会比较大,如果全部加载进来就会占用较多的内存,那么在这个时候,不在显示区域内的对象不去加载。就会节约内存。
4、不在视觉焦点的,可适当缩小。
游戏玩家的视觉焦角一般都集中主角上,对于不在视觉焦点区的,可以采用按比例缩小图片的实际尺寸,在游戏里还原到100%的尺寸。这种方式也可以减少内存的占用。具体的缩小比例,大天使主程陈策的建议为:怪物、武器、翅膀可以缩放到67%,技能25%或50%。
智能优化
除了以上种种人工优化方式,LayaAir引擎将在2.0的版本中推出智能优化。主要功能是将大量的CacheAs静态缓存优化,由手动变成了引擎的自动优化。
最大的好处就是大幅降低了开发者的优化门槛,只需要设置一个属性,就可以开启或关闭智能优化。开启智能优化后,至少可缩短10天的优化工作量。而且可以把很多很难发现的优化点一次性优化成功。优化效果方面,不同的项目会有所差异,FPS的提升在2倍以上。
END