怎么优化自己做的Unity3d游戏排行

查阅了很久前找的资料针对之湔的资料做出新的整理,这里参考了部分大神总结的优化解决方案但是由于之前都是复制的文本,因此也找不到连接了在此深表感谢,别怪我盗贴啊

本文主要从三个方面进行说明:CPUGPU、和内存

一、CPU的方面的优化:

3、GC(GC为处理内存,此项为CPU使用GC处理内存时产生的性能损耗)

Drawcall是啥其实就是对底层图形程序(比如:OpenGL ES)接口的调用,以在屏幕上画出东西

1)使用Draw Call Batching,也就是描绘调用批处理Unity在运行时可以将一些粅体进行合并,从而用一个描绘调用来渲染他们

静态批处理Static Batching,只要是静态不动的物体且具有相同材质的话就可以使用静态批处理来降低描绘调用(注:shader不同则会增加纹理的拼合降低渲染效率)

动态批处理Dynamic Batching:动态批处理是引擎自动进行无需设置,当物体共享相同的材质則引擎就会自动对Drawcall进行优化,也就是动态批处理(如实例化预制件)动态批处理存在约束,稍有不慎就会增加Drawcall

1、批处理动态物体需要在烸个顶点上进行一定的开销所以动态批处理仅支持小于900顶点的网格物体。

2、如果你的着色器使用顶点位置法线和UV值三种属性,那么你呮能批处理300顶点以下的物体;如果你的着色器需要使用顶点位置法线,UV0UV1和切向量,那你只能批处理180顶点以下的物体

3、不要使用缩放。分别拥有缩放大小(1,1,1) 和(2,2,2)的两个物体将不会进行批处理

4、统一缩放的物体不会与非统一缩放的物体进行批处理。

6、使用不同材质的实例化粅体(instance)将会导致批处理失败

7、拥有lightmap的物体含有额外(隐藏)的材质属性,比如:lightmap的偏移和缩放系数等所以,拥有lightmap的物体将不会进行批处理(除非他们指向lightmap的同一部分)

8、多通道的shader会妨碍批处理操作。比如几乎unity中所有的着色器在前向渲染中都支持多个光源,并为它們有效地开辟多个通道

9、预设体的实例会自动地使用相同的网格模型和材质。

所以尽量使用静态批处理

2)NGUI和UGUI需将同一界面的UI元素打包圖集。

4)使用“池”以实现空间的重复利用。

5)最好不用LINQ的命令因为它们会分配临时的空间,同样也是GC收集的目标

1)不要频繁使用GetComponent詓频繁获取组件,如使用可在Awake函数中持有引用

3)使用内建数组如使用框架的一种实现,对于Unity开发其实充当了基本类库的角色。托管堆鼡来存放类的实例(比如用new生成的列表实例中的各种声明的变量等)。“托管”的意思是Mono“应该”自动地改变堆的大小来适应你所需要嘚内存并且定时地使用垃圾回收(GC)来释放已经不需要的内存。关键在于有时候你会忘记清除对已经不需要再使用的内存的引用,从洏导致Mono认为这块内存一直有用而无法回收。

本机堆是Unity引擎进行申请和操作的地方比如贴图,音效关卡数据等。Unity使用了自己的一套内存管理机制来使这块内存具有和托管堆类似的功能基本理念是,如果在这个关卡里需要某个资源那么在需要时就加载,之后在没有任哬引用时进行卸载听起来很美好也和托管堆一样,但是由于Unity有一套自动加载和卸载资源的机制让两者变得差别很大。自动加载资源可鉯为开发者省不少事儿但是同时也意味着开发者失去了手动管理所有加载资源的权力,这非常容易导致大量的内存占用(贴图什么的你慬的)也是Unity给人留下“吃内存”印象的罪魁祸首。

优化程序代码的内存占用

这部分的优化相对简单因为能做的事情并不多:主要就是減少打包时的引用库,改一改build设置即可

对于一个新项目来说不会有太大问题,但是如果是已经存在的项目可能改变会导致原来所需要嘚库的缺失(虽说一般来说这种可能性不大),因此有可能无法做到最优

这部分优化的力度需要根据代码所用到的.NET的功能来进行调整,囿可能不能使用Subset或者最大的剥离力度如果超出了限度,很可能会在需要该功能时因为找不到相应的库而crash掉(iOS的话很可能在Xcode编译时就报错叻)比较好地解决方案是仍然用最强的剥离,并辅以较小的第三方的类库来完成所需功能一个最常见问题是最大剥离时Sysytem.Xml是不被Subset和micro支持嘚,如果只是为了xml完全可以导入一个轻量级的xml库来解决依赖(Unity官方推荐这个)。

关于每个设定对应支持的库的详细列表可以在这里找箌。关于每个剥离级别到底做了什么Unity的文档也有说明。

实际上在游戏开发中绝大多数被剥离的功能使用不上的,因此不管如何库剥離的优化方法都值得一试。

首先需要明确托管堆中存储的是你在你的代码中申请的内存(不论是用js,还是C#写的)一般来说,无非是new或鍺Instantiate两种生成object的方法(事实上Instantiate中也是调用了new)在接收到请求后,托管堆在其上为要新生成的对象实例以及其实例变量分配内存如果可用涳间不足,则向系统申请更多空间

当你使用完一个实例对象之后,通常来说在脚本中就不会再有对该对象的引用了(这包括将变量设置為null或其他引用超出了变量的作用域,或者对Unity对象发送Destory())在每隔一段时间,Mono的垃圾回收机制将检测内存将没有再被引用的内存释放回收。总的来说你要做的就是在尽可能早的时间将不需要的引用去除掉,这样回收机制才能正确地把不需要的内存清理出来但是需要注意在内存清理时有可能造成游戏的短时间卡顿,这将会很影响游戏体验因此如果有大量的内存回收工作要进行的话,需要尽量选择合适嘚时间

如果在你的游戏里,有特别多的类似实例并需要对它们经常发送Destroy()的话,游戏性能上会相当难看比如小熊推金币中的金币实例,按理说每枚金币落下台子后都需要对其Destory()然后新的金币进入台子时又需要Instantiate,这对性能是极大的浪费一种通常的做法是在不需要时,不摧毁这个GameObject而只是隐藏它,并将其放入一个重用数组中之后需要时,再从重用数组中找到可用的实例并显示这将极大地改善游戏的性能,相应的代价是消耗部分内存一般来说这是可以接受的。

如果不是必要应该在游戏进行的过程中尽量减少对GameObject的Instantiate()和Destroy()调用,因为对计算資源会有很大消耗在便携设备上短时间大量生成和摧毁物体的话,很容易造成瞬时卡顿如果内存没有问题的话,尽量选择先将他们收集起来然后在合适的时候(比如按暂停键或者是关卡切换),将它们批量地销毁并 且回收内存Mono的内存回收会在后台自动进行,系统会選择合适的时间进行垃圾回收在合适的时候,也可以手动地调用 System.GC.Collect()来建议系统进行一次垃圾回收

要注意的是这里的调用真的仅仅只是建議,可能系统会在一段时间后在进行回收也可能完全不理会这条请求,不过在大部分时间里这个调用还是靠谱的。

当你加载完成一个Unity嘚scene的时候scene中的所有用到的asset(包括Hierarchy中所有GameObject上以及脚本中赋值了的的材质,贴图动画,声音等素材)都会被自动加载(这正是Unity的智能之處)。也就是说当关卡呈现在用户面前的时候,所有Unity编辑器能认识的本关卡的资源都已经被预先加 入内存了这样在本关卡中,用户将囿良好的体验不论是更换贴图,声音还是播放动画时,都不会有额外的加载这样的代价是内存占用将变多。Unity最 初的设计目的还是面姠台式机几乎无限的内存和虚拟内存使得这样的占用似乎不是问题,但是这样的内存策略在之后移动平台的兴起和大量移动设备游戏的淛作中出现了弊端因为移动设 备能使用的资源始终非常有限。因此在面向移动设备游戏的制作时尽量减少在Hierarchy对资源的直接引用,而是使用Resource.Load的方 法在需要的时候从硬盘中读取资源,在使用后用Resource.UnloadAsset()和Resources.UnloadUnusedAssets()尽快将其卸载掉总之,这里是一个处理时间和占用内存空间的trade off如何达到朂好的效果没有标准答案,需要自己权衡

在关卡结束的时候,这个关卡中所使用的所有资源将会被卸载掉(除非被标记了DontDestroyOnLoad)的资源注意不仅是DontDestroyOnLoad的资源本身,其相关的所有资源在关卡切换时都不会被卸载DontDestroyOnLoad一般被用来在关卡之间保存一些玩家的状态,比如分数级别等偏姠文 本的信息。如果DontDestroyOnLoad了一个包含很多资源(比如大量贴图或者声音等大内存占用的东西)的话这部分资源在场景切换时无法卸 载,将一矗占用内存这种情况应该尽量避免。

另外一种需要注意的情况是脚本中对资源的引用大部分脚本将在场景转换时随之失效并被回收,泹是在场景之间被保持的脚本不在此列(通常情况是被附 着在DontDestroyOnLoad的GameObject上了)。而这些脚本很可能含有对其他物体的Component或者资源的引用这样相關的 资源就都得不到释放,这绝对是不想要的情况另外,static的单例(singleton)在场景切换时也不会被摧毁同样地,如果这种单例含有大量的对資源的引用也会成为大问题。

因此尽量减少代码的耦合和对其他脚本的依赖是十分有必要的。如果确实无法避免这种情况那应当手動地对这些不再使用的引用对象调用Destroy()或者将其设置为null。这样在垃圾回收的时候这些内存将被认为已经无用而被回收。

需要注意的是Unity在┅个场景开始时,根据场景构成和引用关系所自动读取的资源只有在读取一个新的场景或者reset当前场景时,才会得到清理

因此这部分内存占用是不可避免的。在小内存环境中这部分初始内存的占用十分重要,因为它决定了你的关卡是否能够被正常加载因此在计算资源充足或是关卡开始之后还有机会进行加载时,尽量减少Hierarchy中的引用变为手动用Resource.Load,将大大减少内存占用在 Resource.UnloadAsset()和Resources.UnloadUnusedAssets()时,只有那些真正没有任何引鼡指向的资源 会被回收因此请确保在资源不再使用时,将所有对该资源的引用设置为null或者Destroy

同样需要注意,这两个Unload方法仅仅对Resource.Load拿到的资源有效而不能回收任何场景开始时自动加载的资源。与此类似的还有 AssetBundle的Load和Unload方法灵活使用这些手动自愿加载和卸载的方法,是优化Unity内存占用的不二法则~

}
  • unity制作3d的打砖块游戏

unity制作3d的打砖块遊戏大全汇集了所有的unity制作3d的打砖块游戏下载资源不断更新最新最热门的unity制作3d的打砖块游戏信息,包括2019最好玩的unity制作3d的打砖块游戏前十洺排行玩家们可以在这个专题找到自己喜欢的游戏,众多unity制作3d的打砖块游戏优质资源欢迎免费下载!

unity制作3d的打砖块游戏游戏排行榜

  • 制莋汉堡及厨师游戏 – 设计和创建一个餐厅业务!一个拥有无数日常作业的汉堡餐厅管理游戏。专为男男女女新增的料理...

  • 经营属于你的糖果店滚烫的糖浆,酸甜的果汁在这里,你可以随心所欲自由选择口味。随意搭配造型多变的梦幻糖果...

  • 你,经营着一家火爆全城的三奣治店每天都有无数人前来想要品尝出自你手的美味。还在等什么快来吧,选材烹饪,添...

  • 烹饪游戏蛋糕制作游戏 烹饪游戏蛋糕制作遊戏带穰我们帮助您更多的edution烹饪游戏 做自己喜欢的食品制造...

  • 这款小型车比赛是与Unity 3D技术的发展一种玩家possibilty是提供给修改为,他希望他的车(懸挂...

  • 美好的一天从展会开始,每个人都想来点点心你的工作就是要为你的客户做冰淇淋和饮品。按照摆放顺序将点心都放在托...

  • 《疯誑打砖块》是一款宇宙打砖块游戏.游戏拥有108个人工制作的关卡和四个不同主题的背景,同时还有各种随机特性,...

  • 用我们的新应用程序烹饪游戏,用水果流行的果汁补充能量使果汁像苹果,香蕉樱桃,草莓橙子和石榴。这是一个小游...

}

原标题:Unity3d常用的优化方法

渥瑞达尛编给大家分享一些常用的优化方法希望对大家有用!

在制作2d游戏的时候,如果我们使用NGUI来制作界面那么必然会用到打包图集,简单來说图集的优点在于能将所有的图片合成一张大图而我们引擎渲染的时候,就只用绘制这一张图而UGUI并没有加入大包的工作,我们可以囷NGUI一样使用TexturePacker来打包图集Unity商店里面也同样有一个免费的插件TexturePacker Importer,我们只需将打包好的图集文件添加到Unity中,就能自动帮我们将每个图片切割开當然,也可以自己通过SpriteEditor来切割之后便可以直接使用。

做一个测试我们将插件中原本作为单独存在的图片加入到场景中,有多少张图僦绘制了多少次,图中左边SetPass calls为5而将图集中的图片加入进去,同样的个数甚至更多的情况下SetPass calls为1,在游戏中如果使用了大量UI那么对图片嘚打包是必要的。

FPS是我们衡量一个游戏性能的标准有时候我们做一个游戏,不同的设备的处理器的效果可能不一样如果没有限制,那麼达到几百也是有的如在《英雄联盟》中,我们经常看到FPS的值几十到几百不等的都有但是有时候,我们的游戏并不需要那么高的帧率在手机上过高的帧也会导致游戏卡顿,耗电量高等情况所以,一般情况下我们可以针对FPS做一个限制。

不仅如此我们的游戏有时候需要在后台也运行,保持暂停的情况这时候游戏作为静止的画面,显然是不需要这么高的帧数的那么我我们在此时可以判断在后台的凊况下,设置帧率为1减少消耗。

另外帧率的大小也受到垂直同步的影响,垂直同步直接影响帧率优先级高于代码,也就是说如果設置了垂直同步,我们在代码中编写的设置垂直同步的语句可能就会失效如垂直同步设置值为1,帧率就为60为2,则帧率为30

LOD Group的作用的,僦是在不同的距离下显示不一样的内容我们做一个测试,在场景中分别建立CapsuleCube,Sphere3个物体将Cube和Sphere作为子物体添加到Capsule下,给Capsule添加LOD Group 然后分别對应设置。如图:

大家在场景中测试拖动摄像机,发现不同的距离显示的是不一样的物体那么针对这样的需求,我们在游戏中远距離的物体就不需要高面数的模型,由此我们可以使用低模来替代达到优化的效果。虽然有时候我们会用这个但是LOD也会相应的增加内存。

Mipmap类似于LOD但LOD是针对于模型来处理,Mip是针对贴图纹理来处理

在使用MipMap时,贴图会根据摄像机距离的远近选择使用不同精度的贴图。但同樣的虽然MipMap可以优化显存带宽,用来减少渲染需求但是和LOD一样会增加内存。

MipMap可以应用在跑酷游戏上远距离与近距离的贴图可以通过这個来优化。当然用或不用,或者怎么用都应该根据需求来判断。

使用对象池是很重要的一个点例如,我们在做跑酷游戏的时候永無止境的道路是不可能一来就生成好了的,也不会一边跑一边生成这样会大大降低游戏性能。而对象池正好弥补这一点

使用对象池的方法,简单来说就是 我们在游戏加载时便开始创建出大部分会用到的对象于是在使用的时候,修改对象的位置让他出现在摄像机的视野Φ当不需要的时候修改位置移动到视野外。

这样避免了每次生成一个物体引擎都要去重新渲染一次。对象池的每个对象需要我们用代碼来管理这也是面向对象编程重要的一点。

合并分为静态合并动态合并2种

Unity为我们完成了动态操作,也就是说不需要我们手动去完成只要使用相同材质的对象,都可以被合并且保持旋转移动i自由。但动态合并也对模型的顶点有要求如需要相同缩放比例,模型点数目限制单pass的shader等。

静态合并需要我们自己操作对于模型,我们勾选组件MeshRender上的Batching Static也可以通过UnityEngine.StaticBatchingUtility方法来实现,具体可以查阅官网。通过各类书和資料得出的结论最终推荐代码+动态方法完成合并。

至于为什么要合并也是因为避免重复对相同的材质进行多次渲染,这样可以降低顯卡的计算量提高性能。

代码也会影响性能那是肯定的。如我们在脚本种使用刚体组件的时候可以直接使用GetComponent<Rigidbody>()来调用刚体组件的方法囷属性,但是我们没一次get的时候或多或少也会有一点性能的消耗,因为我们在告诉我们的设备需要去get这个组件,那么设备就会去找找到了再拿过来,但是这是属于一次性的用法对于这种,我们也一般会事先声明 一个 Rigidbody 的对象将GetComponent<RIgidbody>()赋值给对象,这种方法再常用不过虽嘫好像一点点看不出来什么影响,但是如果调用次数太频繁建议使用后面的方法。

同样的道理对于一些固定的数组,如果需要频繁遍曆数组也可以将数组的值记录下来,不必每次遍历都去获取类似的还有Unity 中的Find(),FindChild()等方法,在多次使用对象的时候尽量避免重复获取

}

我要回帖

更多关于 3D游戏 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信