深圳Unity3D培训
达内深圳龙华中心

185-8926-6248

热门课程

Unity3D游戏场景优化之批处理

  • 时间:2016-03-24 10:32
  • 发布:深圳Unity3D培训
  • 来源:达内新闻

最近开始研究Unity3D游戏场景优化,每次提及游戏优化这个话题的时候,我的脑海中都会浮现出《仙剑奇侠传六》这个让四路泰坦都光荣陨落的神奇游戏,作为一个使用Unity3D引擎进行游戏开发的仙剑玩家,我曾经天真的以为,这款使用Unity3D引擎打造的仙剑二十周年献礼之作,会让我对《仙剑奇侠传》这个系列游戏的未来充满更多期待,然而当游戏真正呈现在我眼前的时候,我感受到了在历代仙剑游戏中从未有过的尴尬和失望,我尴尬的是Unity3D这样一个比较强大的游戏引擎硬生生地被北软玩成了这个鬼样子,我失望的是这部游戏除了剧情和跳跳乐以外并没有什么让人看到希望的东西。


我知道我这样说会有一堆仙剑玩家指责我说,仙剑本来就是玩剧情的嘛,所以只要剧情好其它的都可以原谅啦。然而我们每一个人都清楚《仙剑奇侠传》是一个RPG游戏,它不是每隔三年出一次新番的GAL动漫、不是每隔三年更新一次的言情小说、更不是每隔三年播放一次的偶像电影。两年前的今天我可以耐着性子玩通关《仙剑奇侠传五》,但是这一次我真的玩不下去了。

当一个游戏因为优化问题而获得《仙剑奇侠传六:泰坦陨落》称号的时候,作为一个玩家我真的不想再为这个游戏洗白什么,虽然我曾经深爱过这个游戏。所以言归正传,作为一个程序员,我们还是来做点程序员该做的事情,那么我们今天说什么呢,我们来说说Unity3D里的批处理!



一、什么是批处理?

我们知道Unity3D在屏幕上绘制一个图形本质上调用OpneGL或者DirectX这样的API,因此在这个过程中会产生一定程度上的性能消耗。DrawCall是OpenGL中描述绘制次数的一个量,例如一个基本的OpenGL绘制流程是设置颜色->绘图方式->顶点坐标->绘制->结束,在绘制的过程中每帧都会重复这个过程,这就是一次DrawCall,所以当游戏中的绘制过程变得复杂的时候,就会带来DrawCall的急剧增加,进而带来游戏的性能问题,反映到游戏表现上就变成了优化问题。

那么在Unity3D中采取了什么样的措施来降低DrawCall呢?这就是我们今天要说的批处理,换句话说Unity3D使用了批处理来达到降低DrawCall的目的,批处理希望通过对物体网格的重组来获得更高的绘制效率,试想以下如果将多个物体合并为一个物体,那么在绘制的时候只需要绘制一次就够了,因此从这个角度上来讲这样做肯定是可以降低DrawCall的,更深刻的一种理解是这里体现了一种资源循环调用的思想,接触过android开发的朋友们一定知道ListView控件可以对其元素进行“缓存”从而提高效率,因为我们可以发现其实ListView是对列表项进行某种程度上的“复用”从而提高了效率,在Unity3D这里同样遵循了这个原理。

在Unity3D中进行批处理的一个前提是相同材质的物体可以被合并,如果这些物体使用不同的材质,那么当我们把这些材质对应的纹理打成“图集”以后可以对其进行合并,并且在合并的时候应该是用Renderer.sharedMaterial 而非 Renderer.material以保证材质是可以共享的。关于DrawCall的相关细节大家从这里来了解,博主并未对图形学领域有过深入的研究,因此就不在这里班门弄斧了啊,哈哈!
 

二、Unity3D中批处理的两种方式

在Unity3D中有静态批处理和动态批处理两种方式,下面我们就来分别说说这两种不同的批处理方式!

静态批处理

静态批处理其实大家都是知道的。为什么这样说呢?因为我们在使用Unity3D的过程中无形中培养了这样一个习惯,那就是将场景中相对来说“静态”的物体都勾选Static选项,这在Unity3D中称为Static GameObjects,并且因为这一特性和Lightmapping、Navigation、Off-meshLinks、ReflectionProbe、Occluder and Occludee等内容均有着密切的联系,因此说静态批处理大家都是知道的其实一点都为过,和场景优化相关的内容博主会在后续的博客中涉及。


静态批处理允许游戏引擎尽可能多的去降低绘制任意大小的物体所产生的DrawCall,它会占用更多的内存资源和更少的CPU资源,因为它需要额外的内存资源来存储合并后的几何结构,如果在静态批处理之前,如果有几个对象共享相同的几何结构,那么将为每个对象创建一个几何图形,无论是在编辑器还是在运行时。这看起来是个艰难的选择,你需要在内存性能和渲染性能间做出最为正确的选择。


在内部,静态批处理是通过将静态对象转换为世界空间,并为它们构建一个大的顶点+索引缓冲区。然后,在同一批中,一系列的“便宜”画调用,一系列的“便宜”,几乎没有任何状态变化之间的。所以在技术上它并不保存“三维的调用”,但它可以节省它们之间的状态变化(这是昂贵的部分)。使用静态批处理非常简单啦,只要勾选物体的Static选项即可!

动态批处理

相对静态批处理而言,动态批处理的要求更为严格一些,它要求批处理的动态对象具有一定的顶点,所以动态批处理只适用于包含小于900个顶点属性的网格。


如果你的着色器使用顶点位置,法线和单光,然后你可以批处理300个顶点的动态对象;而如果你的着色器使用顶点位置,法线,uv0,UV1和切线,那么只能处理180个顶点的动态对象。接下来最为重要的一点,如果动态对象使用的是不同的材质,那么即使进行了动态批处理从效率上来讲并不会有太大的提升。如果动态对象采用的是多维子材质,那么批处理是无效的。

如果动态对象接收实时光影,同样批处理是无效的。点击原文链接查看代码~

这段脚本的核心是CombineMeshes()方法,该方法有三个参数,第一个参数是合并实例的数组,第二个参数是是否对子物体的网格进行合并,第三个参数是是否共享材质,如果希望物体共享材质则第三个参数为true,否则为false。

上一篇:达内深圳龙华android ios游戏开发设计培训机构哪家好?
下一篇:Unity3D Quaternion各属性和函数测试

马上预约三天免费体验课

姓名:

电话:

怎么学Unity3D?新手学Unity3D的学习路线建议

学unity3d开发要学习哪些编程语言

深圳VR培训告诉你unity3d要如何学习

学unity3d技术开发VR的就业前景怎么样

选择城市和中心
贵州省

广西省

海南省