笔者介绍:姜雪伟,IT公司技术合伙人,IT高级讲师,CSDN社区专家,特邀编辑,畅销书作者,国家专利发明人;已出版书籍:《手把手教你架构3D游戏引擎》电子工业出版社和《Unity3D实战核心技术详解》电子工业出版社等。
内存优化不论是游戏开发还是软件开发,都会涉及到这个问题,这个也是所有程序员绕不过的问题,必须要解决的。特别是在移动端盛行的时代,由于硬件的限制,这个问题愈发显得突出。开发者在使用游戏引擎编程或者使用脚本预言编程也会遇到此类问题,在脚本Lua的内存管理方面,开发者尤其要重点关注,因为Lua不仅应用在客户端也应用在服务器端。
记得我一个朋友告诉我,他们的服务器脚本使用的是Lua语言,在登陆人数达到几百个人时,服务器的内存开始吃紧,为解决这个问题找了一段时间发现是Lua造成的,在内存释放方面处理的不是很好。在这里也是提醒开发者使用脚步语言时要留心内存占用,下面主要是以Unity为例给开发者介绍一下关于内存以及优化方面的解决方案。
使用Unity开发移动端游戏时,会遇到各种奇葩问题,首当其冲的问题就是包体大小,由于Unity引擎自身的问题,我们只能自己去减少包体大小,减少包体大小主要是从这几个方面考虑供参考:
第一、图片的使用,图片一般使用的格式是不带有Alpha通道的图片格式是jpg,带有Alpha通道的图片格式是png。接下来我们还可以对图片进行压缩,我们使用的是网上比较流行的压缩方式,网址:www.tinypng.com。当然也可以使用软件压缩,只要保证其像素损失控制在一定范围内即可。
第二、图片控制了,接下来就是使用图集,图集主要是优化内存加载效率问题,一张大的图集内存加载一次即可,如果是多张小图片内存就要不停的加载,释放。说白了利用图集主要是用空间换时间。Unity自身的图集工具不能充分利用空间大小,Unity自身的图集比如如果使用2048*2048大小的图集,即使图集不满,它占的内存还是4M。这个就不理想,推荐使用Texturepackd打包工具,它可以充分利用图集占用空间。
第三、接下来是考虑图片的利用了,做游戏开发我们就要考虑多语言版本问题,这就要求我们的UI尽量保持一致,减少特殊的UI制作,通常多个语言包是放在一个包体中的,在制作时这个问题也是要考虑的。
第四、UI也需要利用Unity自带的图片压缩格式,比如ETC针对Android,PVRTC针对ios的压缩,以及图片大小的压缩,这个主要是针对图标的比如大小可以将其控制在512以下。
第五、考虑到场景的制作了,场景制作我们要控制模型的面数和模型使用材质的数量,这个要分清主次的,有的要体现细节可以多做几张贴图,只是为了装饰使用的物体,用一张材质就能表现,针对场景的制作可以设置好图片库,场景中所有的物件都是使用里面的图片。可以对这些图片认为的把它们打包成图集,也是为了优化内存,自己要分好类的。
第六、场景的制作要采用Prefab的方式,不要在max中把整个场景制作好,而是只制作单个的物件,由美术去自己利用Unity编辑器摆放物件制作场景。最后将场景采用json文件的方式将其保存,用于场景的加载时使用。
第七、如果场景实在是太大了,可以采用多线程的方式在后台加载,这个事情在我写的极客头条《Unity3D实战之多线程下载资源》中有阐述,这里就不详细说了。
第八、角色的制作,角色的材质也是要进行渲染的比如,角色有高光、法线、环境映射等效果,这些效果可以只在选择角色时进行处理,放到场景中后,如果遇到效率问题可以将其材质替换掉。因为在场景中玩家只关注玩法和装备了,对角色的材质关心比较弱化了。
以上是在制作时注意的问题,接下来就是代码这块的优化了,代码的编写注意几个问题:
一、能用单例的尽量少用静态,单例在程序中只保留一份,而静态是多个。
二、对于重复使用的物体,必须要使用对象池对其统一管理。
三、对一些资源加载能够造成卡顿的,使用预加载的方式。
四、不要在Update中定义变量或者使用循环语句,因为它是每帧都在执行的。
五、协成也尽量少用,它不是多线程。
六、后处理渲染尽量少用。
七、程序编码中尽量少用递归的处理方式,遇到实在躲不过了,将其换成堆栈。
八、对代码多一些重构处理,程序的架构设计必须是耦合性低,易于扩展。
以上主要是从大的方面介绍的,遇到特殊问题要特殊对待,比如我在跟北京一家公司的CTO讨论问题时,他说了一个这样的问题,在用手机测试游戏时,有10款手机,在九款手机上是没有问题的,但是在一款手机上特别耗内存,他问我这样的问题该如何解决,遇到此类问题,别无他法,两种选择,一种是放弃这种机型,二是找到问题,我选择了后者,这样的问题就是要特殊对待了,只能采用逐步分析的方法,先找到是什么问题导致的,很多人会说内存问题,大家别忘记一个前提在九款不同类型的机器上是没有问题的,只在一款有问题,解决方式是:我们只能从简单的场景开始测试,这样比较容易定位到问题,大家遇到问题也是一样的,可以做个小的Demo测试,这样更容易定位问题。在这里要注意的是不要等到最后才去测试,要在做的过程中边测试边修改。
另一个案例就是做了一款项目,资源经过优化还是特别大,最后采用了多线程资源下载把问题解决了,上面有提到过,在编写代码时要不停地对其重构。
我在CSDN学院专门为优化做了一个视频讲座,将项目开发中遇到的问题在此做了一个总结:视频名字是:《Unity内存优化经验分享》。解决问题的经验就是不断的从项目中获得的。