iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > 其他教程 >Unity中的静态批处理和动态批处理操作
  • 440
分享到

Unity中的静态批处理和动态批处理操作

2024-04-02 19:04:59 440人浏览 独家记忆
摘要

前言 Unity在运行时可以将一些物体进行合并,从而用一个绘制调用来渲染他们。这一操作,我们称之为“批处理”,能得到越好的渲染性能。 Unity中内建的批处理机制所达到的效果要明显强

前言

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

Unity中内建的批处理机制所达到的效果要明显强于使用几何建模工具的批处理效果,因为,Unity引擎的批处理操作是在物体的可视裁剪操作之后进行的,处理的几何信息少很多。

材质

只有拥有相同材质的物体才可以进行批处理,因此,你需在程序中尽可能多地复用材质。如果你的两个材质仅仅是纹理不同,那么你可通过纹理拼合来将这两张纹理拼合成一张大的纹理,这样,你就可以使用这个单一材质来替代之前的两个材质了。

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

动态批处理

如果动态物体共用着相同的材质,那么Unity会自动对这些物体进行批处理,动态批处理操作是自动完成的,并不需要你进行额外的操作。

Dynamic Batching启用时,Unity将尝试自动批量移动物体到一个Draw Call中。要使物体可以被动态批处理,它们应该共享相同的材质,但是还有一些其他约束条件:

批处理动态物体需要在每个顶点上进行一定的开销,所以动态批处理仅支持小于900顶点的网格物体;如果你的着色器使用顶点位置,法线和UV值三种属性,那么你只能批处理300顶点以下的物体;如果你的着色器需要使用顶点位置,法线,UV0,UV1和切向量,那你只能批处理180顶点以下的物体。

尽量不要使用缩放尺度(scale)。分别拥有缩放尺度(1,1,1)和(2,2,2)的两个物体将不会进行批处理;统一缩放尺度的物体不会与非统一缩放尺度的物体进行批处理。使用缩放尺度(1,1,1)和 (1,2,1)的两个物体将不会进行批处理,但是使用缩放尺度(1,2,1)和(1,3,1)的两个物体将可以进行批处理。

拥有光照贴图的物体有其他渲染器参数,例如光照贴图索引或光照贴图的偏移与缩放。一般来说,动态光照贴图的游戏对象应该指向完全相同的光照贴图的位置。

多通道(Pass)的shader会妨碍批处理操作。比如,几乎unity中所有的着色器在前向渲染中都支持多个光源,并为它们有效地开辟多个通道,这就会要求额外的渲染次数,所以绘制 “额外的每像素灯”时不会被批处理。

静态批处理

为了更好地使用静态批处理,你需要明确指出哪些物体是静止的,并且在游戏中永远不会移动、旋转和缩放。想完成这一步,你只需要在检测器(Inspector)中将Static复选框打勾即可。只要这些物体不移动,并且拥有相同的材质。因此,静态批处理比动态批处理更加有效,你应该尽量低使用它,因为它需要更少的CPU开销。

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

最后,如果场景自带静态物体,会合并批次,这个大家都知道;如果静态物体是场景加载后再读取预制体动态加载进去的,就不会自动合并批次,需要你加载完后调一下手动合并批次的接口,StaticBatchingUtility.Combine 合并。

补充:在Unity3D中的渲染优化-批处理技术

在Unity3D中,常用的减少Draw call的优化技术就是批处理技术。批处理的原理是减少每一帧需要的Draw call数目。为了把一个对象渲染到屏幕上,CPU需要检查哪些光源影响了该物体,绑定shader并设置它的参数,再把渲染命令发送给GPU。当场景中包含了大量的对象时,这些操作就会非常耗时。例如,如果我们需要渲染一千个三角形,把它们按一千个单独的网格进行渲染所花费的时间要远远大于渲染一个包含一千个三角形的网格。在这两种情况下,GPU的性能消耗其实并没有多大的区别,但CPU的draw call数目就会成为性能瓶颈。因此,批处理的思想很简单,就是在每次调用draw call时尽可能多地处理多个物体。

使用同一材质的物体可以进行批处理,因为对于使用同一材质的物体,它们之间的不同仅仅在于顶点数据的差别。我们可以把这些顶点数据合并在一起,再一起发送给GPU,这样就可以完成一次批处理。

在Unity中支持两种类型的批处理,一种是动态批处理,另一种是静态批处理。对于动态批处理来说,优点是一切处理Unity自动完成的,不需要我们做任何操作,而且物体可以是移动的,缺点是限制有很多,可能一不小心就会破坏了这种机制,导致Unity无法动态批处理一些使用了相同材质的物体。而对于静态批处理来说,它的优点是自由度很高,限制很少;但缺点是可能会占用更多的内存,而经过静态批处理后的所有物体都不可以再移动了(即便在脚本中尝试改变物体的位置也是无效的)。

Unity3D中的动态批处理技术

动态批处理的原理是,每一帧把可以进行批处理的模型网格进行合并,再把合并后的模型数据传递给GPU,然后使用同一个材质对其渲染。除了实现方便,动态批处理的另一个好处就是,经过批处理的物体仍然可以移动,这是由于在处理每帧时Unity都会重新合并一次网格。

虽然Unity的动态批处理不需要我们进行任何额外工作,但只有满足条件的模型和材质才可以被动态批处理。(需要注意的是,随着Unity版本的变化,这些条件也有一些改变)这些条件限制是:

1.能够进行动态批处理的网格的顶点属性规模要小于900.例如,如果shader中需要使用顶点位置,法线和纹理坐标这三个顶点属性,那么要想让模型能够被动态批处理,它的顶点数目不能超过300.需要注意的是,这个数字在未来有可能会发生变化,因此不要依赖这个数据。

2.一般来说,所有对象都需要使用同一缩放尺度(可以是(1,1,1),(1,2,3),(1.5,1.4,1.3)等,但必须都一样)。一个例外情况是,如果所有的物体都是用了不同的非统一缩放,那么他们也是可以被动态批处理的。但在Unity5中,这种对模型缩放的限制已经不存在了。

3.对于使用光照贴图纹理的物体需要小心处理。这些物体需要额外的渲染参数,例如,在光照贴图纹理上的索引和偏移量以及缩放信息等因此,为了让这些物体可以被动态批处理,我们需要保证它们指向光照贴图纹理中的同一个位置。

4.有多个Pass通道的shader会中断批处理。在前向渲染中,我们有时需要使用额外的Pass来为模型添加更多的光照效果,但这样一来模型就不会被动态批处理了。

Unity3D中的静态批处理技术

静态批处理的实现原理是,只在运行的开始阶段,把需要进行静态批处理的模型合并到一个新的网格结构中,这意味着这些模型不可以在运行时刻被移动。但由于它只需要进行一次合并操作,因此比动态批处理更加高效。但静态批处理的缺点是需要占用更多的内存来存储合并后的几何结构。这时因为,如果在静态批处理前一些物体共享了相同的网格,那么在内存中每一个物体都会对应一个该网格的复制品,即一个网格会变成多个网格再发送给GPU。如果这类使用相同网格的对象很多,那么这就会成为一种性能瓶颈了。例如,如果在一个使用了1000个相同树模型的森林中使用静态批处理,那么就会多使用1000倍的内存,这会造成严重的内存影响。这时的解决方法就是要么忍受这种牺牲内存换取性能的方法,要么不要使用静态批处理,而使用动态批处理技术(但要小心控制模型的顶点属性数目),或者自己编写批处理方法。

在Unity中使用静态批处理的方法是,在场景中选中需要静态批处理的物体,在其Inspector面板的右上角勾选上Batching static静态属性。在内部实现上,Unity首先把这些静态物体变换到世界空间下,然后为它们构建一个更大的顶点和索引缓存,对于使用同一材质的物体。Unity只需要调用一个drawcall就可以绘制全部物体。而对于使用不同材质的物体,静态批处理同样可以提升渲染性能。尽管这些物体仍然需要调用多个draw call,但静态批处理可以减少这些draw call之间的状态切换,而这些切换往往是费时的操作。

我们可以在Unity的分析器中观察到应用静态批处理前后VBO total(Vertex Buffer Object,顶点缓存对象)的变化。在一些物体共享了相同的网格的情况下,我们可以看到这些物体在使用了静态批处理技术后,VBO total的数目变大了,这正是因为静态批处理会占用更多内存的缘故。正如上面所讲,静态批处理需要占用更多的内存来存储合并后的几何结构,如果一些物体共享了相同的网格,那么在内存中每个物体都会对应一个该网格的复制品。

如果场景中包含了除了平行光以外的其他光源,并且在Shader中定义了额外的Pass来处理它们,这些额外的Pass部分是不会被批处理的,但是处理平行光的Base Pass部分仍然会被静态批处理。

Unity3D中使用共享材质

无论是动态批处理还是静态批处理,都要求模型之间需要共享同一个材质。但不同的模型之间总会需要有不同的渲染属性,例如,使用不同的纹理,颜色等。这时我们需要一些策略来尽可能的合并材质。

如果两个材质之间只有使用的纹理不同,我们可以把这些纹理合并到一张更大的纹理中,这张更大纹理被称为是一张图集(atlas)。一旦使用了同一纹理,我们就可以使用同一材质,再使用不同的采样坐标对纹理采样即可。

但有时除了纹理不同外,不同的物体在材质上还有一些微小的参数变化,例如,颜色不同,某些浮点属性不同。但是,不管是动态批处理还是静态批处理,它们的前提都是使用同一个材质。是同一个,而不是使用了同一shader的材质,也就是说它们指向的材质必须是同一个实体。这意味着,只要我们调整了参数,就会影响到所欲使用这个材质的对象。那么想要微小的调整怎么办呢?一种常用的方法就是使用网格的顶点数据来存储这些参数(最常见的就是顶点颜色数据)。

经过批处理后的物体会被处理成更大的VBO发送给GPU,VBO中的数据可以作为输入传递给顶点着色器,因此,我们可以巧妙地对VBO中的数据进行控制,从而达到不同效果的目的。一个例子就是,森林场景中的所有树使用了同一材质,我们希望它们可以通过批处理来减少draw call,但不同树的颜色可能不同。这时,我们可以利用网格顶点的颜色数据来调整。

需要注意的是,如果我们需要在脚本中访问共享材质,应该使用Renderer.sharedMaterial来保证修改的是和其他物体共享的材质,但这意味着修改会应用到所有使用该材质的物体上。另一个类似的api是Renderer.material,如果使用Renderer.material来修改材质,Unity会创建一个该材质的复制品,从而破坏批处理在该物体上的应用。

关于在Unity3D中使用批处理的注意事项:

1.尽可能的使用静态批处理,但要时刻小心对内存的消耗,并且记住经过静态批处理的物体不可以再被移动。

2.如果无法进行静态批处理,而要使用动态批处理的话,那么尽可能减少物体的数目并且让这些物体包含少量的顶点属性和顶点数目。

3.对于游戏中的小道具,例如可以捡拾的金币等,可以使用动态批处理。

4.对于动画的这类物体,我们无法全部使用静态批处理,但其中如果有不动的部分,可以把这部分标识成“Static”。

5.由于批处理需要把模型变换到世界空间下再合并它们,因此,如果shader中存在一些基于模型空间下坐标的运算,那么往往会得到错误的结果。一个解决方法是,在shader中使用DisableBatching标签强制使该shader的材质不会被批处理。

6.使用半透明材质的物体通常需要使用严格的从后往前的绘制顺序来保证透明混合的正确性。这意味着,当绘制顺序无法满足时,批处理无法在这些物体上被成功地应用。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持编程网。如有错误或未考虑完全的地方,望不吝赐教。

--结束END--

本文标题: Unity中的静态批处理和动态批处理操作

本文链接: https://www.lsjlt.com/news/123256.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Unity中的静态批处理和动态批处理操作
    前言 Unity在运行时可以将一些物体进行合并,从而用一个绘制调用来渲染他们。这一操作,我们称之为“批处理”,能得到越好的渲染性能。 Unity中内建的批处理机制所达到的效果要明显强...
    99+
    2022-11-12
  • React18之状态批处理的使用
    目录状态自动批处理17版 18版 退出状态自动批处理 要点概述react在3月29号正式发布了18版本, 此次更新包括: 状态自动批处理, 客户端渲染a...
    99+
    2022-11-13
  • 解析Spring中的静态代理和动态代理
    目录一、静态代理1.1、静态代理的使用1.2、与装饰者模式的区别二、动态代理2.1、JDK 动态代理2.2、CGlib 动态代理实现一、静态代理 1.1、静态代理的使用 静态代理,代...
    99+
    2022-11-12
  • Windows批处理实现邮件远程控制电脑的操作方法(第三方批处理)
    目录1.收发邮件getmail收邮件的用法blat发邮件的使用2.电脑使用的邮箱3.原理概述3.1执行命令3.2文件传输3.3含有中文的命令3.4隐藏运行3.5开机运行&防止...
    99+
    2023-01-04
    Windows批处理邮件远程控制电脑 Windows批处理远程控制电脑 Windows批处理 批处理远程控制
  • bat批处理之字符串操作的实现
    目录对于字符串的截取字符串的替换字符串合并字符串查找bat批处理代码通常情况下,任何一种语言对于字符串的操作都是重中之重。这里稍微介绍下bat批处理中对于字符串的操作。 对于字符串的...
    99+
    2022-11-13
  • Java中动态代理和静态代理的示例分析
    这篇文章主要介绍了Java中动态代理和静态代理的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。0、代理模式为什么要学习代理模式?这是SpringAOP的底层【Spri...
    99+
    2023-06-29
  • 使用springboot对外部静态资源文件的处理操作
    目录springboot对外部静态资源文件的处理1、存方面倒还简单,这里贴上一个获取微信临时素材并保存的方法2、取,由于对springboot不熟悉,所以在这上面踩了坑主要使用到这2...
    99+
    2022-11-12
  • Python自动化之批量处理工作簿和工作表
    目录一、批量新建并保存工作簿二、批量打开一个文件夹下的所有工作簿三、批量重命名一个工作簿中所有工作表四、批量重命名工作簿五、在多个工作簿中批量新增/删除工作表六、批量打印工作簿七、将...
    99+
    2022-11-12
  • python中的netCDF4批量处理NC文件的操作方法
    目录一、使用ArcMap提取出第一期数据1.使用工具箱中的“Make NetCDF Raster Layer”工具,提取出一个数据2.导出该数据作为标准数据二...
    99+
    2022-11-13
  • 如何理解Java多态中的动态绑定和静态绑定
    如何理解Java多态中的动态绑定和静态绑定,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。在多态中:成员变量和静态方法编译和运行都看左边;成员方法编译看左边,运行看右边,这是为什...
    99+
    2023-06-02
  • 批处理FOR中的Delims和Tokens怎么用
    这篇文章主要为大家展示了“批处理FOR中的Delims和Tokens怎么用”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“批处理FOR中的Delims和Tokens怎么用”这篇文章吧。在For命令...
    99+
    2023-06-09
  • spring boot中的静态资源加载处理方式
    1.spring boot默认资源处理Spring Boot 默认为我们提供了静态资源处理,使用 WebMvcAutoConfiguration 中的配置各种属性。spring boot默认加载文件的路径是:/META-INF/resour...
    99+
    2023-05-31
    spring boot 静态资源
  • BAT批处理中文件与文件夹操作的示例分析
    这篇文章将为大家详细讲解有关BAT批处理中文件与文件夹操作的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。批处理中的文件、文件夹操作,xcopy命令的用法。一,建bat文件自动执行复制,删除命令。...
    99+
    2023-06-08
  • Python批量处理工作簿和工作表的实现示例
    目录批量新建并保存工作簿批量打开一个文件夹中的打开工作簿批量重命名一个工作簿的所有工作表批量重命名多个工作簿批量重命名多个工作簿中的同名工作表将一个工作簿的所有工作表批量复制到其他工...
    99+
    2022-11-12
  • Python自动化之批量处理工作簿和工作表的示例分析
    这篇文章主要介绍Python自动化之批量处理工作簿和工作表的示例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!一、批量新建并保存工作簿import xlwings as xw&nbs...
    99+
    2023-06-15
  • DOS批处理中%cd%和%~dp0的区别是什么
    这篇文章主要讲解了“DOS批处理中%cd%和%~dp0的区别是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“DOS批处理中%cd%和%~dp0的区别是什么”吧!在DOS的批处理中,有时候...
    99+
    2023-06-08
  • 怎么利用python实现windows的批处理及文件夹操作
    今天就跟大家聊聊有关怎么利用python实现windows的批处理及文件夹操作,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。1.批量处理所谓的批处理就是批量处理cmd里面的命令。py...
    99+
    2023-06-22
  • 如何利用python实现windows的批处理及文件夹操作
    目录1.批量处理2. 文件夹操作2.1 读取文件中的文件名2.2 创建文件夹2.3、获取某指定目录下的所有文件的列表2.4、将一个路径名分解为目录名和文件名两部分总结1.批量处理 所...
    99+
    2022-11-12
  • Laravel项目中伪静态分页处理的示例分析
    这篇文章给大家分享的是有关Laravel项目中伪静态分页处理的示例分析的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。下面由Laravel教程栏目给大家介绍Laravel 项目 伪静态分页处理  ,希望对...
    99+
    2023-06-06
  • 批处理中delims=和tokens=星号的区别有哪些
    这篇文章主要介绍批处理中delims=和tokens=星号的区别有哪些,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!比较以下两段代码的执行结果差异: 1、 @echo off for /f "delims=...
    99+
    2023-06-09
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作