我的编程空间,编程开发者的网络收藏夹
学习永远不晚

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

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

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

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

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

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

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

下载Word文档

猜你喜欢

HBase的批处理操作性能如何

HBase的批处理操作性能通常表现良好,特别是在处理大量数据时,通过优化策略可以进一步提升性能。以下是关于HBase批处理操作性能的相关信息:HBase批处理操作性能优化批量写入:通过合并多个写入操作,减少网络通信和操作开销。批量读取:
HBase的批处理操作性能如何
2024-10-19

详解Java中的静态代理和动态代理

在代理模式(Proxy Pattern)中,一个类代表另一个类的功能。这种类型的设计模式属于结构型模式。在代理模式中,我们创建具有现有对象的对象,以便向外界提供功能接口。

Java中动态代理和静态代理的示例分析

这篇文章主要介绍了Java中动态代理和静态代理的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。0、代理模式为什么要学习代理模式?这是SpringAOP的底层【Spri
2023-06-29

Windows批处理实现邮件远程控制电脑的操作方法(第三方批处理)

这篇文章主要介绍了Windows批处理实现邮件远程控制电脑(第三方批处理),本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
2023-01-04

PHP接口性能优化之批量操作与事务处理(PHP接口中批量操作与事务处理的性能优化)

为优化PHP接口性能,请遵循以下提示:批量执行SQL语句或合并查询,并缓存常用查询结果。使用事务处理并释放锁,以避免死锁和提高性能。使用索引、ORM和APC/Opcache优化服务器配置。定期监控和分析性能,并根据需要进行调整。
PHP接口性能优化之批量操作与事务处理(PHP接口中批量操作与事务处理的性能优化)
2024-04-02

如何理解Java多态中的动态绑定和静态绑定

如何理解Java多态中的动态绑定和静态绑定,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。在多态中:成员变量和静态方法编译和运行都看左边;成员方法编译看左边,运行看右边,这是为什
2023-06-02

小心处理 C++ 静态变量中的陷阱

非局部变量的销毁顺序与它们被初始化的顺序相反。不同源文件中的非局部变量以未定义的顺序初始化,这意味着它们的销毁顺序也是未定义的。
C++静态变量2024-11-30

批处理FOR中的Delims和Tokens怎么用

这篇文章主要为大家展示了“批处理FOR中的Delims和Tokens怎么用”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“批处理FOR中的Delims和Tokens怎么用”这篇文章吧。在For命令
2023-06-09

BAT批处理中文件与文件夹操作的示例分析

这篇文章将为大家详细讲解有关BAT批处理中文件与文件夹操作的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。批处理中的文件、文件夹操作,xcopy命令的用法。一,建bat文件自动执行复制,删除命令。
2023-06-08

分时操作系统与批处理操作系统的区别是什么?

分时操作系统与批处理操作系统是两种不同的操作系统类型,它们在任务管理、用户交互和资源分配方式上存在显着差异。本文将深入探讨这两者的区别,并提供示例代码来演示其关键机制。
分时操作系统与批处理操作系统的区别是什么?
2024-03-05

spring boot中的静态资源加载处理方式

1.spring boot默认资源处理Spring Boot 默认为我们提供了静态资源处理,使用 WebMvcAutoConfiguration 中的配置各种属性。spring boot默认加载文件的路径是:/META-INF/resour
2023-05-31

MyBatis中怎么处理动态表名和列名

在MyBatis中处理动态表名和列名可以使用动态SQL语句和动态SQL标签来实现。以下是一个示例:动态表名:
MyBatis中怎么处理动态表名和列名
2024-04-08

Beam中怎么实现数据的批处理和流处理混合模式

在Beam中实现数据的批处理和流处理混合模式可以通过使用Beam的UnboundedSource和BoundedSource接口来实现。这两个接口分别用于定义无界数据流和有界数据集的数据源。在混合模式下,我们可以将无界数据流作为输入,然后
Beam中怎么实现数据的批处理和流处理混合模式
2024-03-15

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录