使用Unity开发安卓游戏怎么进行安卓开发性能优化化

Unity3D(19)
& & 几周前,我开始写一款叫Sky Blocks的游戏,使用Unity引擎并且发布在了安卓手机上,如果你有时间可以在Google Play上下载体验一下。
& & 在写这个游戏的过程中,我遇到的问题大部分都是性能方面的。下面我来介绍一下这款游戏,以及性能问题的解决方案。
& & 这款游戏混合了《俄罗斯方块》和《太空入侵者》这两个游戏的玩法。玩家将方块尽量的摆成一条线,方块会从下往上运动,最后停在屏幕的最顶端,但是不会想《俄罗斯方块》那样连成线以后就立即消失。你有60秒的时间摆出尽量多的线,时间一到就会有UFO入侵你完成的防御工事,一旦它们将你的防御都摧毁以后就会攻打地球,当地球的生命值为零游戏就结束了。
& & 这游戏听上去挺简单的,但要做好还得下些功夫,不过,这样才有意思,非常有意思!
写代码前一定要计划好
& & 写代码之前一定要计划好,这非常重要。我在开始开发Sky Blocks之前就没有想好要做什么,没有考虑清楚游戏的玩法。在正式开发Sky Blocks之前我走了一些冤枉路,我用JavaScript和HTML5写了一个《俄罗斯方块》游戏,后来又用C#将其移植到Unity,但是在移植的过程中没有考虑二维和三维的区别,仅仅是复制粘贴的做法,遇到碰撞检测的bug也只是做了小幅的调整。
& & 因为没有简单的在每次刷新时更新整个游戏面板,所以我将整个面板都布满一个最简单的方块,这些方块用来作为背景网格定位。每次网格刷新时都会将所有方块销毁然后重新实例化,对于我来说,这样做已经很不错了,在电脑上运行的很流畅。
& & 一般,一个面板上会有20行10列的网格,有可能会不断地有200个背景方块需要渲染、销毁、重建。另外,还会有不断增加的防御线(10个方块每行),每个方块都会有自己的材料,每个材料都会绘制。假如,一个游戏面板上有150-200个方块需要渲染,那么,就会调用大约200次的绘制函数。
& & 如果我在动手之前有明确的计划,我就会发现这么做游戏是不会运行太久,有可能就会在一开始就省去我大部分时间。
& & 在动手之前画一个草图是一个好主意,这样就可以通过整体分析找到哪些内容是不变的?这些内容有什么不同?在Sky Blocks这游戏中是游戏面板、防御线和UFO。
& & 游戏面板用来控制游戏,包括可移动的方块和已经锁定住的静态方块。
& & 防御线由10个方块组成并排在一条线上。UFO都是由网格组成,它们可以在防御线上面移动。抓住这几点,我就接近成功了!
减少绘制函数调用
& & 我之前也提到过,我的实现方式会大量调用绘制函数。当在安卓设备(三星galaxy S4)上运行游戏,随着游戏内容越来多,我发现游戏变得越来越卡了。& & 为了让游戏运行流畅,我首先考虑减少绘制函数的调用次数。我在网上查相关资料,绘制函数会消耗多少资源?怎么造成的?该怎么优化?&
& 意识到效率问题,我不能出一个好的测试方案,找到一些测例会对CPU和GPU造成严重的压力就行。一些测例没有太大的影响,但有些则会让我的帧率变得很低。
& & 影响效率的问题还是比较容易发现,其根源就是不同的方块有不同的材质。
& & 要减少绘制函数的调用就得减少object的数量和材质数量。
& & 因此,我写了一段代码用来生成一个网格,这个网格就可以替代原来有200个立方体组成的游戏面板。然后,我用顶点着色的方法替代贴图方法。最后,我将材质的着色器换成在网上找到的一个不发光的顶点着色。现在我将所有重复的绘制函数调用都减少为只调用一次!
& & 对于防御线的处理,我用了类似的方法。我将所有材质都替换成了不发光的顶点着色,我没将它们用一个网格代替,而是保留了10个立方体,因为,替换了材质就已经不再多次调用绘制函数了。
& & 非常遗憾,我事先没有准备,所以这里没有提供优化前后的区别对比图片。下面是一个已经优化好的游戏截图:
& & 上图目前这个方块只调用了一次绘制函数(Batches:20、SetPass calls:20),之前提到每个方块由4-5个立方体组成,这个方块就处理了4次。
& & 现在,已经放置了两个方块,但处理次数只增加了一次。若是之前的版本,每激活一个方块中的一个立方体都会处理一次。
& & 防御线也是同一种模式,但实际上有10个四边形,它们采用顶点着色法并且共享材质。这个例子中,我们没必要将防御线做成一个网格来绘制,因为,Unity会通过“Saved by batching”来自动处理这个问题。
& & UFO比较棘手。每一个UFO都由上中下三块网格组成,因为,我想让UFO的外观是随机组成的。UFO的每一部分包含3-4个材质,那么一个UFO很有可能就会调用12-17次绘制函数,而实际上会调用17-30次。会有2-3个UFO同时出现在屏幕上,那么就会调用50-100次绘制函数,该死!
& & 对于这点,我迫切的想要减少绘制函数的调用次数,所以我在网上找到了一个脚本,它可以将这些网格合并为一个。但是这个脚本不可以处理材质的问题,于是我最终将UFO都着成一个颜色,这样UFO变得非常丑。我手动改了一下那个脚本,现在UFO可以绘制最多2种颜色了。来看看行得通吗?现在只调用了30次绘制函数,但是我也不确定运行效率是否真的有所提升,不过至少我将每个UFO绘制函数的调用次数减少到了10次以下。
& & 减少绘制函数的调用次数是不是适合所有的情况呢?当然不是。如果你可以减少当然最好,但是对于有些非常棘手的部分,只有通过牺牲显示效果来提升效率。
& & 现在,对于绘制函数调用次数的优化,我已经从150-200次减少到了75-90次,还是很不错的!
& & 最后,轮到UFO发射的激光,它们也都是单独的材质,当UFO进入狂暴状态时,绘制函数需要调用30-40次。非常幸运,这次只需要建立一个原始的四边形,它使用不发光的顶点着色法,这样,所有的激光只需要调用一次绘制函数,即使是UFO都进入了狂暴状态。
现在,游戏中所有的绘制函数减少到了30-45次,不错不错!剩下的就是UI中的绘制函数了,但是UI的处理我没有找到好的办法,不过我还是非常满意现在的效率了,现在游戏比之前运行得流畅许多。
& & UFO还是占了一部分绘制函数,但是考虑到已经从30减少到了不到10次,还是有很大进步。
& & 一个首要的原则就是使用尽量少的材质,如果可以,最好共享材质而不是每一个都实例化,这样,会减少很多绘制函数调用次数。
资源只加载一次
& & 在我的一些代码中,我使用了一些Resource.Load函数,但是由于Unity不会将已经加载的资源缓存下了,所以游戏运行中就会反复加载资源,这样非常消耗效率。我之前就会把激光的材质反复加载,这样虽然不会在PC上有什么影响,但是在安卓设备上就不行了。
& & 为了避免反复加载游戏资源,我建立了一个静态的Dictionary(资源名称为Key,资源为value),当我要用某个资源的时候我会先去查询字典中是否有对应的Key,若是没有才会加载资源,反之,我就直接用缓存的资源。
避免多次调用Instantiate函数
& & 我没有考虑过GameObject.Instantiate函数的开销,在代码中大量的使用了它,我本以为这个函数的开销也就和new一个类对象一样,但是,我错了!在GameObject的新建与销毁时都比较消耗CPU。然而,我在实现UFO攻击的时候就遇到了这个问题,每当UFO开火时都会新建一个激光束,然后再非常短的时间内又将其销毁,这样,在短短1.5秒内就有可能调用20-40次新建与销毁函数。太棒了!我终于找到UFO攻击时性能不高的原因了。
& & 解决这个问题的方法就是做一个对象池。我构建了一个空的对象池,当我需要新建激光束的时候,我会先去检查对象池中是否已经存在,如果存在,改变一下它的位置与血量就可以直接用了。
& & 如果对象池中没有我想要的,我就会像之前一样新建一个。当在需要销毁这个对象时,我并没有直接销毁,而是又将其交还给对象池,然后将其设置为非激活状态。通过对象池的方法,在UFO攻击的时候CPU的开销降低了25-30%!
& & 绘制函数开销非常大,你应该尽量减少调用次数。减少材质数量可以非常有效的减少绘制函数调用。少用不同的贴图,可以将多张贴图烘培在一个图集里面。如果2D游戏就少用光照,甚至可以像我这样做,不要光照只用色彩描述就可以了。着色器不要带有参数,而是用不发光的顶点着色,我这个项目中就是这样做的。以上这些可以大大减少绘制函数的调用次数。如果你觉得这样视觉效果达不到你的要求,你可以试试增加一些网格。
& & Instantiate函数非常慢,所以尽量少用它。在游戏一开始你可以将大部分你经常需要用到的对象构建好放在对象池中,要用的时候只需要将其激活。
绘制函数和Instantiate函数并不是唯一优化对象,绘制函数销耗CPU和GPU,Instantiate函数消耗CPU。
如果你有一个非常精细的模型或者一个过程非常耗时,这时减少绘制函数并不能起到什么作用。优化CPU的消耗时重中之重,你可以梳理你的代码,看看是否有大量重复执行的内容,然后想办法优化它们。
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:119925次
积分:1658
积分:1658
排名:第18462名
原创:15篇
转载:47篇
译文:20篇
评论:33条
(2)(8)(3)(3)(6)(3)(8)(16)(3)(2)(3)(3)(4)(1)(3)(6)(3)(2)【视频学堂】51CTO IT教学视频课程索引~【学人堂】
51cto,IT教育?课程索引
云计算|OpenStack|虚拟化|云平台|其他|Office 365|云服务|Docker|其他大数据|Spark|Hadoop|Storm|Hive|Yarn|其他移动开发|Swift|微信开发|iOS|Android|HTML5|移动测试|WinPhone|其他游戏开发|Cocos2d-x|Unity3D|手游开发|3D游戏|开发工具|其他系统/运维|Linux|Windows|Unix|Mac os|其他考试认证|软考|Linux认证|华为认证|思科认证|微软认证|H3C认证|等级考试|其他编程语言|Java|C/C++|Python|.Net|Ruby|Go语言|其他Web开发|PHP|JavaScript|Html/CSS|jQuery|XML/XSL|Dreamweaver|其他软件研发|软件测试|敏捷开发|研发管理|软件设计|软件架构|其他网络技术|网络管理|路由交换|安全技术|通信技术|数据中心|其他服务器存储|Windows Server|Exchange|Lync|SharePoint|Nginx|集群|分布式|邮件服务器|其他数据库|Oracle|MySQL|SQL Server|Access|Sybase嵌入式|嵌入式Linux|驱动/内核开发|单片机/工控|物联网|智能硬件|其他企业信息化|项目管理|ERP|管理软件Office|Excel|PPT|Word|其他设计|交互设计|平面设计|室内设计|其他大学MOOC|计算机网络|数据结构|计算机导论|算法基础|软件工程|操作系统|其他其它|IT职场|网络营销|多媒体|互联网运营游戏性能优化的经验谈
招聘信息:
文/优化概论说起游戏的优化,在游戏开发中经常分为这几步:首先要确定游戏中经常会出现哪些问题 - Profile然后确定在哪些方向进行性能优化 - Analyze最后再尽可能将问题逐个解决 - Solve游戏开发中一定是先做工具,进行Profile,再进行优化,所以,说优化就不得不再扯一下Profile常见的工具有一些是引擎和IDE自带的,比如Unity自带的Profiler,就包含了CPU,GPU,Memory等等各式各样的性能分析工具,其他的比如GPA,Xcode Instrument和Visual Studio,Intel自带的内存管理工具在必要的时候也使需要去学习和使用的。另外一些工具,就需要根据游戏的需求去编写了,比如一键关闭所有特效,一键更改分辨率等等,一键设置场上NPC数量,简单的游戏如啪啪三国是做成快捷键开启Profile功能的,更为复杂的游戏如神秘海域则是通过游戏内控制台来进行更为细致的Profie。接着,我们再来说说游戏优化中主要的四个考虑方向:CPU引发的问题:由于短时间内的计算量太大,导致画面流畅性降低,俗称跳帧发热严重,耗电量高常见的优化手段:将计算分到多个逻辑帧中进行计算,避免短时间内的性能超过负荷,俗称“分帧”(time-slice)。将可以缓存的数据尽可能的缓存起来,避免重复计算和重复分配内存,常见的示例为“内存池”。使用合理的算法和数据结构,比如:冒泡排序和直接插入排序在整体数组比较有序的情况下效率大大好于快速排序。把快排替换成是优化程序排序效率的一个常见的思路。GPU引发的问题:发热严重,耗电量高FPS降低常见的优化手段:优化美术资源,比如合理规划图集,约定好模型的最大三角形面数,制定合理的粒子效果规范。这个可以说是游戏优化中最重要的一个,因此,技术美术在游戏开发中作用巨大。简化或者优化着色器(shader),如在游戏开始前就对Shader进行编译和加载。使用Batching,尽量减少DrawCall使用平台推荐的压缩格式,比如安卓平台的ETC1和IOS平台的PVRTCIO和网络引发的问题:网络延迟甚至掉线加载资源导致的跳帧加载时间过长常见的优化手段:使用独立的线程进行加载,有些引擎如Unity中还能利用协程减少网络包里面的冗余数据合并小包,减少请求数据的次数分帧对回包进行处理限制一定时间内的发包频率内存引发的问题:闪退和卡死,比如安卓的Low Memory Killer会在低内存情况下杀掉内存占用过大的程序。常见的优化手段:动态加载和卸载资源,比如在游戏内的时候,我们可以把游戏外的一些UI图集卸载掉。降低资源质量或屏幕分辨率,这是有损优化,一般作为最后的手段对做过项目的一些思考需要关注非功能性需求这一点思考是我从“”这个答案中想到的,正如这位答主所说:“事实上,从我的经验来看,一般来说,很多软件项目及产品,其在非功能性需求上的成本,难度和工作量,是要超过功能性需求的。在特定的软件领域,例如网站(尤其是淘宝,facebook这样海量用户规模的网站),金融(银行证券),电信领域,其非功能性需求实现的重要性,工作量,技术难度要远远远远大于功能性需求的实现。而且,功能性的需求的实现,其实在大多数情况下,更依赖于业务的高手(或者好的产品经理)而不是技术的高手,而非功能性需求的实现,恰恰是挑战技术高手的重要课题。”在游戏前端这边做了一段时间,大家都在抱怨游戏前端技术含量低,只能写业务逻辑,但是其中的陷阱就是,作为前端,你应当尽量少写业务逻辑,你关注过一下的模块吗?性能:你有没有在自己的游戏中进行Profile,观察在以上各个参数有没有达到指标安全:你的游戏前端代码的Release版本是否还能被别人轻易反编译,你的游戏是否还能轻易被玩家截取网络包或修改内存数据可测试性:你的前端代码能不能进行单元测试,能不能在QA测试之前就把Model层的所有bug解决掉数据驱动:你能不能做出更优秀的工具来给美术和策划使用,解放他们的生产力?需要善于划定范围,缩小问题区间我在过去几个月里,参加了全民突击和崩坏学园2两个Unity3D项目的开发,也遇到了一些性能优化相关的问题,在程序出现问题时,很多时候我们会通过所谓的“经验”去解决问题,这种Quick Link的能力自然是非常重要,但经验并非万能。但是从另一方面来讲,当我们无法从自己过往的经验中找到答案的时候,我们就要通过划分范围,缩小问题区间来解决问题了,许多人往往只是在自己的经验中死守一个局部的视野去处理问题,最后的结果就一定不能尽如人意。总结其实这四个方面的优化总是相互制衡的,你把一个方面的优化做好了,另一个方面的问题又会出现了,比如,我们如果使用动态加载和卸载资源,这就虽然减少了内存占用量,会在IO上造成加载时间延长的问题。所以,我们在做游戏优化的时候,不能太追求完美,刚刚好就是真的好(Good Enough Is Fine)。最终使得以上这四个方面能达到均衡即可,切忌在某一方面优化过头,又引发其他方面的问题,此消彼长的情况下,有时反而不如不做优化。
微信扫一扫
订阅每日移动开发及APP推广热点资讯公众号:CocoaChina
您还没有登录!请或
点击量6444点击量6351点击量5861点击量5539点击量5088点击量4510点击量4302点击量3728点击量3692
&2016 Chukong Technologies,Inc.
京公网安备89君,已阅读到文档的结尾了呢~~
基于unity3d的android街机游戏开发关键技术的分析
扫扫二维码,随身浏览文档
手机或平板扫扫即可继续访问
基于unity3d的android街机游戏开发关键技术的分析
举报该文档为侵权文档。
举报该文档含有违规或不良信息。
反馈该文档无法正常浏览。
举报该文档为重复文档。
推荐理由:
将文档分享至:
分享完整地址
文档地址:
粘贴到BBS或博客
flash地址:
支持嵌入FLASH地址的网站使用
html代码:
&embed src='/DocinViewer--144.swf' width='100%' height='600' type=application/x-shockwave-flash ALLOWFULLSCREEN='true' ALLOWSCRIPTACCESS='always'&&/embed&
450px*300px480px*400px650px*490px
支持嵌入HTML代码的网站使用
您的内容已经提交成功
您所提交的内容需要审核后才能发布,请您等待!
3秒自动关闭窗口

我要回帖

更多关于 unity2d项目性能优化 的文章

 

随机推荐