温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

Render中关于Unity渲染优化的方法是什么

发布时间:2022-01-11 15:42:49 来源:亿速云 阅读:131 作者:iii 栏目:大数据

本篇内容介绍了“Render中关于Unity渲染优化的方法是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

哪些属于渲染产生的性能问题?

首先,要明确一点:整个渲染工作只有当CPU和GPU完成了各自全部的任务时,才能成功渲染出一帧画面。任意一个任务执行超时,都会导致整个这一帧的渲染延时。

渲染问题一般可分为两类,第一种是由低效的渲染管线引起的。渲染工作中的一步或多步耗时过长,执行效率低下,打断了平滑的数据流,便会导致低效的渲染管线,这种现象我们也称之为 渲染瓶颈(bottlenecks)。第二种是由于一口气向渲染管线发送过多的指令引起的渲染瓶颈。

当我们发现游戏里渲染一帧需要很长的时间,而且与CPU的执行效率有关,这种情况我们称之为 CPU瓶颈(CPU bound)。同样的,当我们发现游戏渲染一帧时间过长与GPU花费了大量的时间进行渲染计算有关,这种情况我们称之为 GPU瓶颈(GPU bound)。

在对我们的代码进行修改之前,通过合适的性能分析工具来定位渲染性能问题很重要,要对阵下药,当然合理的对我们的修改进行评估也很重要。性能优化是一种权衡行为,可能对这方面性能的改善会给其他部分带来负面影响。

两种性能分析工具

Profiler窗口工具

Render中关于Unity渲染优化的方法是什么  
Profiler窗口工具

Profiler 窗口 工具可以让你实时监控游戏性能的表现。我们可以通过Profiler工具看到我们游戏中的许多方面,包括内存使用情况,渲染管线使用情况,以及用户脚本使用情况(代码质量)。

Frame Debugger

Render中关于Unity渲染优化的方法是什么  
Frame Debugger窗口

Frame Debugger 可以让我们看到游戏每一帧是如何一步步渲染的。它可以让我们看到更多的细节,包括每一个draw call它让GPU渲染了哪些东西,它影响了shader代码块中的哪些属性 以及 CPU 发送给GPU的事件,这些信息将帮助我们理解我们的游戏是如何渲染的,并且该如何改进我们的性能表现。


如果渲染问题是由CPU瓶颈(CPU bound)引起的

一般来说,CPU这部分工作与渲染相关的步骤如下:

  1. 决定要被渲染的对象

  2. 准备要发送给GPU的数据

  3. 发送指令给GPU

这些步骤由许多独立的任务组成,而这些任务又多线程来处理。多线程可以同时处理多个任务。这意味着整个渲染工作可以更快。我们也称这种工作模式为多线程渲染(multithreaded rendering)。

Unity的渲染进程主要由三种类型的线程来执行:主线程,渲染线程,工作线程。

主线程主要是处理CPU的大多数任务,包括部分渲染任务。

渲染线程顾名思义,专门是处理那些CPU发送给GPU的指令的任务。

工作线程中的每个线程各自都处理一个任务,比如一些剔除任务或材质蒙皮任务。

至于哪些任务由哪些线程来处理主要取决于我们在项目中的 设置(settings)以及我们项目运行的 硬件设备(hardware)。比如,内核越多的CPU,就拥有更多的工作线程。因此,同一款游戏在不同的设备可能表现截然不同。

由于多线程渲染是一项复杂且依赖硬件设备的工作,我们在优化方面就必须考虑是什么导致了我们的CPU瓶颈。如果问题是出在CPU花费了很多时间执行剔除工作这个线程上,那么你从CPU发送指令到GPU的这件事上进行优化也是于事无补的,因为它们不在同一个线程。

当然,也不是所有的平台都支持多线程渲染,至少在写这篇文章时,WebGL还不支持这个功能。如果一台设备不支持多线程渲染,所有的CPU任务都将被同一个线程执行,这样虽然在渲染效率上不如其他设备,但是一旦发生了CPU瓶颈,你的任何针对CPU方面的优化手段都会提升CPU的表现。

Graphics jobs选项

这个选项用户可以通过打开player settings找到

Render中关于Unity渲染优化的方法是什么  
PlayerSettings

它的功能是决定unity是否使用工作线程来处理渲染的任务,如果不勾选,则主要还是使用主线程或渲染线程。在支持graphics jobs的平台上,勾选该选项,可以很大提升性能表现。大家可以自行测试观察性能效果。

向GPU发送渲染指令

一帧向GPU发送过多的渲染指令,在 CPU瓶颈(CPU bound)中是最常见的问题,这个任务在大多数的平台上都是发生在渲染线程上,但是某些平台(如PS4等)是发生在工作线程上。

这类任务中开销最大的操作要归咎于向GPU发送 SetPass call 的指令,减少它的请求次数是优化这类任务的最佳手段。

我们可以通过Profiler窗口中 Rendering的部分看到到底有多少SetPass call和batch被发送到GPU。当然,根据目标硬件的不同,对SetPass call的数量的承受度是不同的,比如PC客户端能接受的数量要比移动设备多许多。

我们可以通过以下手段来减少SetPass call和 batch的数量:

  • 减少被渲染物体的数量可以减少 SetPass call 和 batch的数量

  • 减少被渲染物体的请求渲染的次数可以减少SetPass calls的数量

  • 将被渲染物体的数据进行合批,可以减少batch的数量

针对这三条,我们进行展开

I . 如何减少被渲染物体的数量?

减少被渲染物体的数量是最简单的方式来提升渲染性能表现,我们可以通过以下几个方法:

  1. 减少在场景中相机可见(视锥体)的被渲染物体的数量。比如,如果我们渲染一群各不相同的角色,我们可以尝试去掉几个,然后看一下效果。这比用复杂的技术去进行优化来的快得多。

  2. 我们可以通过使用相机的 远裁减平面(Far Clip Plane)属性进行控制,这一点跟第一条的原理是一样的。

  3. 我们可以通过改变相机的 远近剔除(Layer Cull Distances)属性来自定义对渲染对象的剔除距离。这种方法一般多应用于非常小的物体(比如草地上的花卉),一旦距离相机超过一定的距离,即使在相机的视锥体内,也不进行渲染。

  4. 我们还可以使用相机上面的 遮挡剔除(occlusion culling)选项,顾名思义,如果一个被渲染对象完全被另一个被渲染对象遮挡(相对于相机),那么它将不会被渲染。但是,occlusion culling 选项并不适用于所有场景,慎用。

II . 如何减少被渲染物体的请求渲染的次数?

我们都知道,实时光照,阴影和反射会给游戏增添许多真实感,但是也会产生巨大的开销。因为他们会导致同一被渲染对象被多次渲染,这将大大影响性能。

其中就拿 渲染路径(rendering path)来说,选择什么样的渲染路径会产生非常大的差异。大多数情况下,如果我们的设备是比较高端的硬件设备,选择 延迟渲染(Deferred Rendering)相比 前向渲染(Forward Rendering)要更合适,因为它的特性可以让你使用更多的实时光照,阴影和反射。而前向渲染更适合低端的硬件设备上,同样的渲染量上,它对于GPU的开销没有那么大。到底谁更好,具体情况具体分析。

动态光照 很昂贵,在优化方式上面也很复杂, 感兴趣的小伙伴可以点击前方传送门。如果场景中有很多被渲染物体不会移动,可以考虑使用 光照烘培(baking)。这样在游戏运行时就可以不用考虑动态光的计算。

阴影 的质量可以通过 Quality Settings 来进行设置,比如,我们可以通过设置阴影距离(Shadow Distance)来控制多少距离以内物体之间会投射阴影。

反射 的优化比较复杂,这里也不展开,留下传送门。

III . 如何将被渲染对象进行合批,减少batch?

被渲染对象必须具备以下要素符合合批条件

  • 共享同一材质实例

  • 有相同的材质配置(贴图,shader,shader参数)

尽管合批渲染对象可以提升渲染性能,但是也需要考虑如何确保合批产生的消耗不超过性能的收益。

以下是一些关于合批的方法:

  1. 静态合批(Static batching),这种方法可以把邻近的符合条件静态的渲染对象进行合批。静态合批会导致较高的内存占用,所以我们也需要考虑它的利弊。

  2. 动态合批(Dynamic batching)是另一种技术,允许unity非静态的对象进行合批,但是有一些限制。同样的,动态合批会导致CPU比较搞的内存使用,我们也需要权衡利弊。

  3. UI方面的合批,UI元素相对来说有一些复杂, 它是受制于我们的UI层。

  4. GPU instancing 选项可以让许多同样的渲染对象非常高效的合批。但是它受限于硬件设备。

  5. Texture atlasing 图集,可以把重复使用的图片合并到一张更大的贴图上。这个技术在2D游戏和UI系统中应用比较多,3D游戏也可以使用。Unity有一个内置图集工具叫做 Sprite Packer。

  6. 我们还可以通过unity编辑或代码人为地对网格和贴图进行合并,当然这么做的话需要知道这些渲染对象的阴影,光照和剔除都仍然会各自处理。这意味着你通过合并材质达到提升性能的目的会与通过剔除渲染对象以至于不渲染它达到的效果相抵消。

  7. 我们需要注意在脚本中当通过 Renderer.material 来对材质进行操作,引擎会复制一份实例并返回它的引用,也就是说你的操作只会在它被复制的实例上进行,不会影响到它原来的材质,如果你想通过代码来修改多个共享材质的渲染对象,你需要使用 Render.sharedMaterial 。

“Render中关于Unity渲染优化的方法是什么”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注亿速云网站,小编将为大家输出更多高质量的实用文章!

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI