位置: 编程技术 - 正文
推荐整理分享【Unity技巧】Unity中的优化技术(2)(unity unit),希望有所帮助,仅作参考,欢迎阅读内容。
文章相关热门搜索词:unity unlit,unity ui,unity-,unity ulua,unity-,unity unit,unity unit,unity ui,内容如对您有帮助,希望把文章链接给更多的朋友!
可以看到Draw Calls一下子变成了5。这是因为新添加的箱子模型中,包含了个顶点,而它使用的顶点属性有位置、UV坐标、法线等信息,使用的总和超过了。
动态批处理的条件这么多,一不小心它就不干了,因此Unity提供了另一个方法,静态批处理。接着上面的例子,我们保持修改后的缩放,但把四个物体的“Static Flag”勾选上:
点击Static后面的三角下拉框,我们会看到其实这一步设置了很多东西,这里我们想要的只是“Batching static”一项。这时我们再看Draw Calls,恩,还是没有变化。但是不要急,我们点击运行,变化出现了。
Draw Calls又回到了3,并且显示Save by batching是1。这就是得利于静态批处理。而且,如果我们在运行时刻查看模型的网,会发现它们都变成了一个名为Combined Mesh (roo: scene)的东西。这个网是Unity合并了所有标识为“Static”的物体的结果,在我们的例子里,就是四个物体:
你可以要问了,这四个对象明明不是都使用了一个材质,为什么可以合并成一个呢?如果你仔细观察上图的话,会发现里面标明了“4 submeshes”,也就是说,这个合并后的网其实包含了4个子网,也就是我们的四个对象。对于合并后后的网,Unity会判断其中使用同一个材质的子网,然后对它们进行批处理。
但是,我们再细心点可以发现,我们的箱子使用的其实是同一个网,但合并后却变成了两个。而且,我们观察运行前后Stats窗口中的“VBO total”,它的大小由.6KB变成了.2KB,变大了!还记得静态批处理的缺点吗?就是可能会占用更多的内存。文档中是这样写的:
“Using static batching will require additional memory for storing the combined geometry. If several objects shared the same geometry before static batching, then a copy of geometry will be created for each object, either in the Editor or at runtime. This might not always be a good idea – sometimes you will have to sacrifice rendering performance by avoiding static batching for some objects to keep a smaller memory footprint. For example, marking trees as static in a dense forest level can have serious memory impact.”
也就是说,如果在静态批处理前有一些物体共享了相同的网(例如这里的两个箱子),那么每一个物体都会有一个该网的复制品,即一个网会变成多个网被发送给GPU。在上面的例子看来,就是VBO的大小明显增大了。如果这类使用同一网的对象很多,那么这就是一个问题了,这种时候我们可能需要避免使用静态批处理,这意味着牺牲一定的渲染性能。例如,如果在一个使用了个重复树模型的森林中使用静态批处理,那么结果就会产生倍的内存,这会造成严重的内存影响。这种时候,解决方法要么我们可以忍受这种牺牲内存换取性能的方法,要么不要使用静态批处理,而使用动态批处理(前提是大家使用相同的缩放大小,或者大家都使用不同的非统一缩放大小),或者自己编写批处理的方法。当然,我认为最好的还是使用动态批处理来解决。
有一些小提示可以使用:
尽可能选择静态批处理,但得时刻小心对内存的消耗。
如果无法进行静态批处理,而要使用动态批处理的话,那么请小心上面提到的各种注意事项。例如:
尽可能让这样的物体少并且尽可能让这些物体包含少量的顶点属性。
不要使用统一缩放,或者都使用不同的非统一缩放。
对于游戏中的小道具,例如可以捡拾的金币等,可以使用动态批处理。
对于包含动画的这类物体,我们无法全部使用静态批处理,但其中如果有不动的部分,可以把这部分标识成“Static”。
一些讨论:
How static batching works
Static batching use a ton of memory?
Unity3D draw call optimization
[color=ize:px]合并纹理(Atlas)
虽然批处理是个很好的方式,但很容易就打破它的规定。例如,场景中的物体都使用Diffuse材质,但它们可能会使用不同的纹理。因此,尽可能把多张小纹理合并到一张大纹理(Atlas)中是一个好主意。
[color=ize:px]利用网的顶点数据
但有时,除了纹理不同外,还有对于不同的物体,它们在材质上还有一些微小的参数变化,例如颜色不同、某些浮点参数不同。但铁定律是,不管是动态批处理还是静态批处理,它们的前提都是要使用同一个材质。是同一个,而不是同一种,也就是说它们指向的材质必须是同一个实体。这意味着,只要我们调整了参数,就会影响到所有使用这个材质的对象。那么想要微小的调整怎么办呢?由于Unity中的规定非常死,那么我们只好想些“歪门邪道”,其中一种就是使用网的顶点数据(最常见的就是顶点颜色数据)。
前面说过,经过批处理后的物体会被处理成一个VBO发送给GPU,VBO中的数据可以作为输入传递给Vertex Shader,因此我们可以巧妙地对VBO中的数据进行控制,从而达到不同效果的目的。一个例子是,还是之前的森林,所有的树使用了同一种材质,我们希望它们可以通过动态批处理来实现,但不同树的颜色可能不同。这时我么可以利用网的顶点数据来调整。具体方法,可以参见后面会写的一篇文章。
但这种方法的缺点就是会需要更多的内存来存储这些用于调整参数用的顶点数据。没办法,永远没有绝对完美的方法。
[color=ize:px]带宽优化
[color=ize:px]减少纹理大小
之前提到过,使用Texture Atlas可以帮助减少Draw Calls,而这些纹理的大小同样是一个需要考虑的问题。在这之前要提到一个问题就是,所有纹理的长宽比最好是正方形,而且长度最好是2的整数幂。这是因为有很多优化策略只有在这种时候才可以发挥最大效用。
Unity中查看纹理参数可以通过纹理的面板:
而调整参数可以通过纹理的Advance面板:
上面各种参数的说明可以参见文档。其中和优化相关的主要有“Generate Mip Maps”、“Max Size”和“Format”几个选项。
“Generate Mip Maps”会为同一张纹理创建出很多不同大小的小纹理,构成一个纹理金字塔。而在游戏中可以根据距离物体的远近,来动态选择使用哪一个纹理。这是因为,在距离物体很远的时候,就算我们使用了非常精细的纹理,但肉也是分辨不出来的,这种时候完全可以使用更小、更模糊的纹理来代替,而这大量可以节省访问的像素的数目。但它的缺点是,由于需要为每一个纹理建立一个图像金字塔,因此它会需要占用更多的内存。例如上面的例子,在勾选“Generate Mip Maps”前,内存占用是0.5M,而勾选了“Generate Mip Maps”后,就变成了0.7M。除了内存的占用以外,一些时候我们也不希望使用Mipmaps,例如GUI纹理等。我们还可以在面板中查看生成的Mip Maps:
Unity中还提供了查看场景中物体的Mip Maps的使用情况。更确切的说是,展示了物体理想的纹理大小。其中红色表示这个物体可以使用更小的纹理,蓝色表示应该使用更大的纹理。
“Max Size”决定了纹理的长宽,如果我们使用的纹理本身超过了这个最大,Unity会对其进行缩小来满足这个条件。这里再重复一点,所有纹理的长宽比最好是正方形,而且长度最好是2的整数幂。这是因为有很多优化策略只有在这种时候才可以发挥最大效用。
“Format”负责纹理使用的压缩模式。通常选择这种自动模式就可以了,Unity会负责根据不同的平台来选择合适的压缩模式。而对于GUI类型的纹理,我们可以根据对画质的要求来选择是否进行压缩,具体可以参见之前关于画质的文章。--来自狗刨学习网
我们还可以根据不同的机器来选择使用不同分辨率的纹理,以便让游戏在某些老机器上也可以运行。
[color=ize:px]利用缩放
很多时候分辨率也是造成性能下降的原因,尤其是现在很多国内山寨机,除了分辨率高其他硬件简直一塌糊涂,而这恰恰中了游戏性能的两个瓶颈:过大的屏幕分辨率糟糕的GPU。因此,我们可能需要对于特定机器进行分辨率的放缩。当然,这样会造成游戏效果的下降,但性能和画面之间永远是个需要权衡的话题。
在Unity中设置屏幕分辨率可以直接调用Screen.SetResolution。实际使用中可能会遇到一些情况,雨松MOMO有一篇文章讲了这种技术,可以去看看。
[color=ize:px]写在最后
这篇文章是总结性质的,因此对每种技术都没有进行非常详细的解释。强烈建议大家阅读文章开头给出的各种链接,写得都很好。
unity3d 性能优化之角色建模 使用一个单一的SkinnedMeshRendere您应该对于每个角色仅使用一个skinnedmeshrenderer。unity使用可见性裁剪和包围体更新的方法来优化角色的运动,并且这些优
Unity3d 调用 C++ 函数 实现加密防破解 (Android向) 因为Unity采用C#作为主要语言,代码编译之后作为DLL存在与执行文件中,这就给我们带来很大的一个问题,反编译非常容易。如何反编译Unity游戏的代码
Unity ShaderLab学习总结 UnityShaderLab学习总结WhyBothers?为什么已经有ShaderForge这种可视化Shader编辑器、为什么AssetStore已经有那么多炫酷的Shader组件可下载,还是有必要学些Shader
标签: unity unit
本文链接地址:https://www.jiuchutong.com/biancheng/375735.html 转载请保留说明!上一篇:Unity3D架构系列之-FSM有限状态机设计(一)(unity3d官方案例)
下一篇:unity3d 性能优化之角色建模(unity3d ugui优化)
友情链接: 武汉网站建设