unity3d 动态合批_unity3d静态合批 - CSDN
  • unity会把使用了相同材质的物体进行动态和批处理,作为一个batch绘画。在unity提供的frame debug中可以清楚的看到每个batch的来由。下面我们来看看如何分析每个batch产生的原因, 项目的结构如下: 1、我们隐藏...

    unity会把使用了相同材质的物体进行动态和批处理,作为一个batch绘画。在unity提供的frame debug中可以清楚的看到每个batch的来由。下面我们来看看如何分析每个batch产生的原因,
    项目的结构如下:
    这里写图片描述

    1、我们隐藏888~1775和color0(1776)这个两个物体。
    看到frame debug如下:
    这里写图片描述

    2、我们打开888~1775
    这里写图片描述
    看到frame debug如下:
    这里写图片描述

    3、我们打开color0(1776)
    这里写图片描述
    看到frame debug如下:
    这里写图片描述

    可以看到合并的最大索引数字为32k,最后color0(1776)没有被合批处理,只能单独画一个mesh。

    下面来看看现在总共几个batch,在Status中可以看到:
    这里写图片描述
    目前为4个batch。
    第一个batch在frame debug中如下:
    这里写图片描述

    第二个batch在frame debug中如下:
    这里写图片描述

    第三个batch在frame debug中如下:
    这里写图片描述

    第四个batch在frame debug中如下:
    这里写图片描述

    注:第一个batch由clear产生;第二个batch为第一次合批处理;第三个batch为第二次合批处理;第四个为单独draw 1776产生。
    ok,本文接下来附上使用到的一个shader如下:

    Shader "Demo/color0"
    {
        SubShader
        {
            Pass
            {
                Tags{"LightMode"="ForwardBase"}
                CGPROGRAM
                #pragma vertex vert
                #pragma fragment frag
                #include "UnityCG.cginc"
                #include "Lighting.cginc"
    
                struct vertOut
                {
                    float4 pos:SV_POSITION;
                    float4 color:COLOR;
                };
    
                vertOut vert(appdata_base v)
                {
                    vertOut o;
                    o.pos = UnityObjectToClipPos(v.vertex);
                    return o;
                }
    
                float4 frag(vertOut i):COLOR
                {
                    return _LightColor0;
                }
                ENDCG
            }
        }
    }

    摄像机的render path为forward模式。为了排除干扰我们还将天空盒的材质球取出来,只关注我们的shader绘制情况。

    unity里面是可以设置是否动态合批处,设置的地方在:File->Build Settings->Player Settings
    这里写图片描述

    当取消勾选Dynamic Batching的时候,就不会再进行动态合批了。

    展开全文
  • draw call是openGL的描绘次数(directX没怎么研究,但原理应该差不多) 一个简单的openGL的绘图次序是:设置颜色→绘图方式→顶点座标→绘制→结束。 每帧都会重复以上的步骤。这就是一次draw call ...

    draw call是openGL的描绘次数(directX没怎么研究,但原理应该差不多)
    一个简单的openGL的绘图次序是:设置颜色→绘图方式→顶点座标→绘制→结束。
    每帧都会重复以上的步骤。这就是一次draw call

    如果有两个model,那么需要  
    设置颜色→绘图方式→顶点座标A→绘制→结束。
    设置颜色→绘图方式→顶点座标B→绘制→结束。
    两次draw calls;
    也就是说在openGl绘制前,如果色彩通道(color filter),绘图方式(shader),顶点座标(model)不同的情况下draw calls就会增加。

    对openGl来说绘制参数(状态值)的变更要比绘制大量的顶点更耗费cpu。

    所谓高速绘图就是,在尽量不改变openGl状态值的情况下,用一次draw call完成所有绘制。
    比如上面的例子:
    设置颜色→绘图方式→顶点座标A+顶点座标B→绘制→结束。
    就要更加有效率。

    个人估计unity3d的dynamic batch,static batch都是通过一定的方法使不同的object的顶点座标能够结合成一个整体,达到减少draw calls的效果。
    但是有一定的要求限制,比如material要相同,mesh要相同并在300个面以内等等,这些都是为了保证openGl的状态值不改变。

     

    Unity在 Player Setting 里的两个功能选项 Static Batching 与 Dynamic Batching。功能描述如下:

    1. Static Batching 是将标明为 Static 的静态物件,如果在使用相同材质球的条件下,Unity 会自动帮你把这两个物件合并成一个 Batch,送往 GPU 来处理。这功能对效能上非常的有帮助,所以是需要付费才有的。
    2. Dynamic Batching 是在物件小于300面的条件下(不论物件是否为静态或动态),在使用相同材质球下,Unity就会自动帮你合合并成一个 Batch 送往 GPU 来处理。

     

    在屏幕上渲染物体,引擎需要发出一个绘制调用来访问图形API(iOS系统中为OpenGL ES)。每个绘制调用需要进行大量的工作来访问图形API,从而导致了CPU方面显著的性能开销。

     

    Unity在运行时可以将一些物体进行合并,从而用一个绘制调用来渲染他们。这一操作,我们称之为“批处理”。一般来说,Unity批处理的物体越多,你就会得到越好的渲染性能。

     

    Unity中内建的批处理机制所达到的效果要明显强于使用几何建模工具(或使用Standard Assets包中的CombineChildren脚本)的批处理效果。这是因为,Unity引擎的批处理操作是在物体的可视裁剪操作之后进行的。Unity先对每个物体进行裁剪,然后再进行批处理,这样可以使渲染的几何总量在批处理前后保持不变。但是,使用几何建模工具来拼合物体,会妨碍引擎对其进行有效的裁剪操作,从而导致引擎需要渲染更多的几何面片。

     

    材质

    只有拥有相同材质的物体才可以进行批处理。因此,如果你想要得到良好的批处理效果,你需要在程序中尽可能地复用材质和物体。

    如果你的两个材质仅仅是纹理不同,那么你可以通过 纹理拼合 操作来将这两张纹理拼合成一张大的纹理。一旦纹理拼合在一起,你就可以使用这个单一材质来替代之前的两个材质了。

    如果你需要通过脚本来访问复用材质属性,那么值得注意的是改变Renderer.material将会造成一份材质的拷贝。因此,你应该使用Renderer.sharedMaterial来保证材质的共享状态。

     

    动态批处理

    如果动态物体共用着相同的材质,那么Unity会自动对这些物体进行批处理。

    动态批处理操作是自动完成的,并不需要你进行额外的操作。

     

    Tips:

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

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

    3、请注意:属性数量的限制可能会在将来进行改变。

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

    5、 统一缩放尺度的物体不会与非统一缩放尺度的物体进行批处理

    使用缩放尺度(1,1,1)和 (1,2,1)的两个物体将不会进行批处理,但是使用缩放尺度(1,2,1)和(1,3,1)的两个物体将可以进行批处理。

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

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

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

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

     

    静态批处理

    相对而言,静态批处理操作允许引擎对任意大小的几何物体进行批处理操作来降低绘制调用(只要这些物体不移动,并且拥有相同的材质)。因此,静态批处理比动态批处理更加有效,你应该尽量低使用它,因为它需要更少的CPU开销。

    为了更好地使用静态批处理,你需要明确指出哪些物体是静止的,并且在游戏中永远不会移动、旋转和缩放。想完成这一步,你只需要在检测器(Inspector)中将Static复选框打勾即可,如下图所示:
     

     
     

    使用静态批处理操作需要额外的内存开销来储存合并后的几何数据。在静态批处理之前,如果一些物体共用了同样的几何数据,那么引擎会在编辑以及运行状态对每个物体创建一个几何数据的备份。这并不总是一个好的想法,因为有时候,你将不得不牺牲一点渲染性能来防止一些物体的静态批处理,从而保持较少的内存开销。比如,将浓密森里中树设为Static,会导致严重的内存开销。

     

    静态批处理目前只支持Unity iOS Advanced。

    展开全文
  • 比如游戏各个模型是独立的,它们的材质以及贴图很有可能是完全一样的,但是由于一些模型数据不一样,放入Unity中会占很多DrawCall,所以Unity提供了一个属性来做静态合批,可以将它们合并在一个Mesh里。 //--设置...

    比如游戏各个模型是独立的,它们的材质以及贴图很有可能是完全一样的,但是由于一些模型数据不一样,放入Unity中会占很多DrawCall,所以Unity提供了一个属性来做静态合批,可以将它们合并在一个Mesh里。

    //--设置静态合批

    首先在Edit→Project Settings→Player中勾选Static Batching静态合批和Dynamic Batching动态合批复选框。

    接着,比如两个Cube都选中Batching Static标记,然后运行游戏。

    Mesh Filter会自动生成一个新的Mesh。

    这样如果有相同材质 Shader 并且参数一致的话,就会合并DrawCall。

    静态合批的最大顶点数是65535,如果定点数超过了它,Unity就会自动合并出多个Mesh。

    //--脚本静态合批

    自动的静态合批用起来很方便,但是也是有隐患。加入场景很大,合并出来的Mesh就会很大。游戏运行后只要有一小部分出现在摄像机内,那么整个大的Mesh都需要参与渲染。还有最大定点数的限制。

    我们可以利用脚本来动态设置需要合并在一起的游戏对象,游戏对象不需要选中Static标记。

    using UnityEngine;
    
    public class StaticBatchingByScript : MonoBehaviour
    {
        public GameObject[] cubes;
    
        private void Start()
        {
            StaticBatchingUtility.Combine(cubes, gameObject);
        }
    }
    

     如图:

     

    代码含义就是将数组中的游戏对象合并在同一个Root节点下,也就是第二个参数。

    另外运行游戏后合并过的Mesh 对象是不可以发生位移的,但是可以移动他们指定的Root节点。

    //--动态合批

    动态合批是全自动的,我们不需要做任何事情。但是它是有要求的,Mesh的顶点数量要小于300。如果Shader中使用了顶点位置 法线 UV0 UV1 和切线,Mesh的定点数必须小于180。(在粒子特效中它发挥了很大的优势)。

    //--静态合批的隐患

    静态合批的原理就是自动生成Mesh,但是不同的Mesh保存的信息可能是不同的。例如Mesh中可能会保存color 和 tangent,但是大部分Mesh都是不需要这个信息的,如果静态合批中有一个Mesh包含了这个信息,那么合并后整个Mesh都会带上它,这样无疑会增加一些额外的开销。

    很多时候是美术在导出FBX时,操作不当导致添加了没用的color 和 tangent信息,所以可以利用FBX官网提供的FBX接口,自己写一个Python脚本来删除它们。

    没有脚本,我不会Python,哈哈。等会了加上。

    展开全文
  • 动态合批与静态合批其本质是对将多次绘制请求,在允许的条件下进行合并处理,减少cpu对gpu绘制请求的次数,达到提高性能的目的。 1.静态合批是将静态(不移动)GameObjects组合成大网格,然后进行绘制。静态合批...

    动态合批与静态合批其本质是对将多次绘制请求,在允许的条件下进行合并处理,减少cpu对gpu绘制请求的次数,达到提高性能的目的。

    1.静态合批是将静态(不移动)GameObjects组合成大网格,然后进行绘制。静态合批使用比较简单,PlayerSettings中开启static batching,然后对需要静态合批物体的Static打钩即可,unity会自动合并被标记为static的对象,前提它们共享相同的材质,并且不移动,被标记为static的物体不能在游戏中移动,旋转或缩放。但是静态批处理需要额外的内存来存储合并的几何体。注意如果多个GameObject在静态批处理之前共享相同的几何体,则会在编辑器或运行时为每个GameObject创建几何体的副本,这会增大内存的开销。例如,在密集的森林级别将树标记为静态可能会产生严重的内存影响。此时就必须去权衡利弊,为了更少的内存占用,可能需要避免某些GameObjects的静态批处理,尽管这必须要牺牲一定的渲染性能。
    静态合批在大多数平台上的限制是64k顶点和64k索引(OpenGLES上是48k索引,macOS上是32k索引)。

    2.动态合批是将一些足够小的网格,在CPU上转换它们的顶点,将许多相似的顶点组合在一起,并一次性绘制它们。
    无论静态还是动态合批都要求使用相同的材质,动态合批有以下限制:

    • 动态合批处理动态的GameObjects的每个顶点都有一定的开销,因此动态合批处理仅应用于包含不超过900个顶点和不超过300个顶点的网格。

      • 如果shader中使用Vertex Position, Normal和single UV,可以批量处理最多300个顶点,而如果shader中使用Vertex Position, Normal, UV0, UV1和Tangent,则只能使用180个顶点
      • 注意:将来可能会更改属性计数限制。
    • 如果GameObjects在Transform上包含镜像,则不会对其进行动态合批处理(例如,scale 为1的GameObject A和scale为-1的GameObject B无法一起动态合批处理)。

      • 为了验证此说法,笔者亲自做了测试,对于两个同样的物体:
        a.一个物体保持scale为(1,1,1),改变另一个物体的scale:
        1).当三个轴向的缩放值为负数(简称负缩放)的个数为偶数时可以合批处理,即scale为(1,1,1)和scale为(-1,-2,3)、(-1,2,-3)、(2,-3,-4),此时三个轴向的负缩放的个数为0个、2个、2个和2个,均为偶数个,可以合批处理,注意正负号,缩放数值可以随便更改;
        2).当三个轴向的负缩放的个数为奇数时可以不能合批处理,即scale为(-1,1,1)、(1,-2,3)、(1,2,-3)和(-2,-3,-4),此时三个轴向的负缩放的个数为1个、1个、1个和3个,均为奇数个,不可以合批处理。
        b.同时改变两个物体的缩放,仍然符合上述的三个轴向的负缩放的个数为奇数个时不合批,偶数个时合批:
        1).A物体(1,2,3),B物体(-1,2,3)、(1,-2,3)、(1,2,-3),奇数个负缩放不合批
        2).A物体(-1,2,3),B物体(-1,2,3),奇数个负缩放不合批,其他组合类似
        3).A物体(-1,-2,3),B物体(1,2,3)、(-1,2,-3),偶数个负缩放,其他组合类似
        总结为:对于两个相同的物体,当两个物体三个轴向的负缩放的个数为偶数个时(0个,2个),可以合批,当两个物体中任意一个物体或者两个物体同时三个轴向的负缩放的个数为奇数个时,不合批。此前有很多文章说对于不同缩放的物体,无论是否为负缩放,均不会合批处理,笔者使用的unity版本是unity2019.1.7f1,可能是因为unity在某个版本已经修复了该问题,有知道的朋友,请告知一声,谢谢。
    • 使用不同的Material实例会导致GameObjects不能一起批处理,即使它们基本相同。阴影渲染(shadow caster)是一个例外,下文会解释为什么。

    • 带有光照贴图的GameObjects有额外的渲染器参数:保存光照贴图的索引和偏移/缩放。一般来说,动态光照贴图的GameObjects应指向完全相同的光照贴图位置才能被动态合批处理。

    • 使用多个pass的shader不会被动态合批处理。

      • 几乎所有Unity Shaders在forward rendering(前向渲染)中都支持多个灯光 ,为了他们有效地进行额外的传递。额外的pre-pixel lights的绘制调用不会被动态合批处理,这个在移动平台上比较少遇到。
      • The Legacy Deferred (light pre-pass) rendering path 中禁用动态批处理,因为它必须绘制两次GameObjects。

    github 上Unity官方总结了25种不能被合批处理的情况, Unity-Technologies/BatchBreakingCause

    动态合批处理的工作是在cpu上将所有GameObject顶点转换到世界空间,因此,如果该工作小于执行绘制调用,则这是一个优势。绘制调用的资源需求取决于多方面的因素,主要是使用的图形API。例如,在 consoles or modern APIs,比如Apple Metal,绘制调用开销通常要低得多,此时动态合批处理就不再是优势了,所以动态合批处理并不是万能的啊。

    动态合批处理(Particle Systems, Line Renderers, Trail Renderers)
    对于Unity动态生成的几何体的组件,动态合批处理与网格相比有不同的工作方式。

    • 对于每个兼容的渲染器类型,Unity将所有可混合内容构建为1个大型顶点缓冲区(Vertex Buffer)。
    • 渲染器为批处理设置材质的状态。
    • Unity将顶点缓冲区(Vertex Buffer)绑定到图形设备。
    • 对于动态合批处理中的每个渲染器,Unity将偏移更新到顶点缓冲区(Vertex Buffer),然后提交新的绘制调用。

    在评估图形设备调用的成本时,渲染组件的最慢部分是材质状态的设置。相比之下,将不同的偏移绘制调用提交到共享顶点缓冲区的速度非常快。

    注意:
    1.不同材质的阴影会动态合批,只要绘制阴影的 pass是相同的,因为阴影跟其他贴图等数据无关
    2.目前,只有 Mesh Renderers, Trail Renderers, Line Renderers, Particle Systems和Sprite Renderers支持合批处理,而skinned Meshes,Cloth和其他类型的渲染组件不支持合批处理。
    3.渲染器仅与其他相同类型的渲染器进行合批处理。
    4.对于半透明的GameObject,按照从前到后的顺序绘制,Unity首先按这个顺序对GameObjects进行排序,然后尝试对它们进行批处理,但由于必须严格满足顺序,这通常意味着对于半透明的材质更少使用合批处理。
    5.手动的合并GameObject是代替合批处理的好办法,比如使用Mesh.CombineMeshes,或者直接在建模时将多个网格合并成单个网格。



    作者:雄关漫道从头越
    链接:https://www.jianshu.com/p/a3087f31ff88
    来源:简书
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

    展开全文
  • 先附上能动态合批的条件: 1.动态批处理仅支持顶点数小于900的网格物体。 2.如果Shader使用了顶点位置、法线、UV值三种属性,则只能动态批处理300个顶点以下的物体。如果Shader使用了顶点位...
  • 半透明粒子特效 Prefab,内含多个 ParticleSystem,复制多个后 DrawCall 增加明显,在FrameDebugger 里发现粒子特效无法动态合批,说是材质球不同,但其实材质球明明是相同的,令人疑惑。 查阅官方文档...
  • 只要材质相同,并Sprite在同一Atlas里,就可以合批。 不论Sorting Layer不同,还是Sorting Order不同。 材质相同的两个不同Sorting Order之间插入一个不同材质会生成3个Draw Call。 Sprite的Mesh Type会影响合批...
  • unity 静态合批

    2019-09-28 22:34:34
    想做这样一个优化 因为cmd drawcall太多 materials太多导致 实际上只是贴图不一样 想用texture2DArray把他们合起来 texArray这步功能倒是很快就好了 ...unity有一个枚举会把不能合批的原因列...
  • unity3d开发中,为了降低场景的运行消耗,通常要利用Unity3d的静态合批动态合批。因为动态合批要求的条件比较苛刻。所以大部分用的都是静态核批。 利用静态核批就需要尽量的合并场景的贴图,用相同的材质。并把...
  • Unity3d渲染 batch rendering http://blog.csdn.net/leonwei/article/details/41942157 渲染(Batch) batch render 是大部分引擎提高渲染效率的方法,基本原理就是通过将一些渲染状态...
  • Unity用户手册-Mesh合批

    2019-04-30 15:34:52
    把很多静止的模型,标记为Batching Static,原本需要把模型一个个送到GPU渲染,Unity会把相同材质相同纹理相同Shader的模型合批成一个大的模型,送到GPU进行渲染,这样就减少DrawCall。可以调用Mesh.CombineMeshes...
  • 为了在屏幕上绘制一个对象,游戏引擎必须发出一个绘制命令给图形化API接口(如OpenGL 或者Direct3D),DrawCalls通常都是资源密集的,图形化API每一次DrawCall都要做很多重要的工作, 会造成CPU一定的性能开销,这...
  • 最近开始研究Unity3D游戏场景优化,每次提及游戏优化这个话题的时候,我的脑海中都会浮现出《仙剑奇侠传六》这个让四路泰坦都光荣陨落的神奇游戏,作为一个使用Unity3D引擎进行游戏开发的仙剑玩家,我曾经天真的以为...
  • 网上看了几篇文章,觉得不如自己试试,果然发现了一些问题,又查了查官网,才知道版本更新的时候批处理也更新了。 新版本官网上的介绍中去掉了缩放的限制,增加了一条对于镜像物体无法进行批处理,比如Scale为(1...
  • Unity在运行时可以将一些物体进行合并,从而用一个绘制调用来渲染他们。这一操作,我们称之为“批处理”。一般来说,Unity批处理的物体越多,你就会得到越好的渲染性能。 Unity中内建的批处理机制
  • 在前面的文章中我介绍了Batch对于渲染效率的影响,这次来说说在Unity开发过程中常用的几种合批技术。   Resource Merging 我们可以在美术资源生产的过程中做很多渲染批次方面的优化。通常我们可以将一些使用...
  • unity-合批优化

    2019-06-09 12:29:20
    编辑器清除控制台日志 public static void ClearConsole... var logEntries = System.Type.GetType("UnityEditorInternal.LogEntries,UnityEditor.dll"); var clearMethod = logEntries.GetMethod("Clear", S
  • 很多刚刚接触Unity3d的童鞋花了大量的时间自学,可总是把握不好Unity3d的烘焙,刚从一个坑里爬出来,又陷入另一个新的坑,每次烘焙一个场景少则几个小时,多则几十个小时,机器总是处于假死机状态,半天看不到结果,...
  • 合批失败问题

    2020-06-15 18:16:27
    合批失败问题 游戏场景中存在大量例子的时候,DrallCall的压力很大,但是遍历一遍之后发现,为啥一样的粒子特效竟然没有合并,why?经过很多测试后发现,如果把透明材质的修改为非半透明的,就可以合并,这就让我很...
  • Unity用户手册-UGUI合批

    2019-03-05 11:04:44
    合批过程是指Canvas合并UI元素的网格,并且生成发送给Unity渲染管线的命令。Canvas使用的网格都是从绑定在Canvas上的CanvasRenderer获得,但是不包含子Canvas的网格。UGUI的层叠顺序是按照Hierarchy中的顺序从上往下...
1 2 3 4 5 ... 20
收藏数 631
精华内容 252
关键字:

unity3d 动态合批