2016-08-01 18:40:26 qq_16072507 阅读数 587
  • Unity3D场景优化算法

    该课程主要是针对密集型场景裁剪处理提供了解决方案,利用四叉树或者八叉树对场景进行分割,然后通过角色身上的包围盒与四叉树或者八叉树分割的物体进行碰撞检测,这样就可以把玩家周围的物体显示出来,这个也是针对移动端的解决方案。如果对于PC端可以使用多线程分块解决,该课程也是给读者提供了一种场景优化的解决方案。

    126 人正在学习 去看看 姜雪伟

1.场景灯光烘焙。

2.遮挡剔除。

3.lod。

2012-03-16 17:19:10 jixuguo 阅读数 930
  • Unity3D场景优化算法

    该课程主要是针对密集型场景裁剪处理提供了解决方案,利用四叉树或者八叉树对场景进行分割,然后通过角色身上的包围盒与四叉树或者八叉树分割的物体进行碰撞检测,这样就可以把玩家周围的物体显示出来,这个也是针对移动端的解决方案。如果对于PC端可以使用多线程分块解决,该课程也是给读者提供了一种场景优化的解决方案。

    126 人正在学习 去看看 姜雪伟

转自:http://unity3dhome.com/thread-790-1-1.html

 

优化的常规技巧

n 剖析你的游戏。 不要花费时间来优化那些晦涩的代码或者缩减图形文件的大小,除非这是你游戏的瓶颈。第一次剖析你的游戏将会使你发现你游戏的瓶颈。Apple's Shark是一个很好的用来剖析基于OpenGL的程序的工具。

n 再次剖析你的游戏。 优化之后不要忘记再剖析一次你的游戏,这样可以检查你所做的优化是否达到了预期的效果。当然,这样做也可能会使你发现更多的瓶颈。

n 流程第一、性能第二。 花费时间来使你游戏的创建尽可能地流畅。尽可能快地修正游戏中的错误将会使你后期更容易优化你的游戏。

n 在Scene View中测试场景。 这样做将会使你清楚了解这个场景中的物体或者附加在物体上的脚本是否降低了游戏性能。如果Scene View反应迟钝,那么有可能是图形方面的原因,如果Scene View反应不迟钝,那么瓶颈可能出在脚本或者物理系统上。

n 禁用指定游戏物体。 在play模式下,尝试禁用并启用游戏物体来排查出游戏慢的原因。



网格

n 如果可能的话,把相邻的物体(网格)合并为一个只有一个材质的物体(网格)。 比如,你的游戏中包含一个桌子,上面有一堆东西,你完全可以在3D程序中将它们合并在一起(这可能也需要你将这些物体的纹理合并为一个大的纹理集)。减少需要渲染的物体的数量可以极大地提高游戏性能。

n 不要有不必要的网格。 如果你的游戏场景中有一个人物,那么他应该是一个网格。如果你有一个船,那么它也应该只是一个网格。

n 每一个网格只用一种材质。

n 使用极少的面数的网格(比如500个多边形以下)。

n 最好把你人物的三角面数量控制在1500-2000个之间。 这个数量可以说是游戏质量和性能之间一个均衡值。如果你的模型有四边形,那么在导入模型的时候,引擎将会把每个四边形变为两个三角形。



光照

n 像素光。 像素光可以让你的游戏看起来效果很牛逼,但是不要使用过多的像素光。在你的游戏中可以使用质量管理器来调节像素光的数量来取得一个性能和质量的均衡点。

n 性能占用顺序:聚光灯>点光源>平行光。 一个好的点亮场景的方法就是先得到你想要的效果,然后看看哪些光更重要;在保持光效的前提下看看哪些光可以去掉。

n 点光源和聚光灯只影响它们范围内的网格。 如果一个网格处于点光源或者聚光灯的照射范围之外,并且光源的attenuate开关是打开的,那么这个网格将不会被光源所影响,这样就可以节省性能开销。这样做理论上来讲可以使用很多小的点光源而且依然能有一个好的性能,因为这些光源只影响一小部分物体。一个网格在有8个以上光源影响的时候,只响应前8个最亮的光源。



贴图

n 在外观不变的前提下,贴图大小越小越好。 如果你的显卡的显存不够大的话,你游戏中的贴图将会被转存到系统内存中,在显卡调用它们的时候再传到显卡中。对于比较新的电脑来说,内存和显卡之间有足够的带宽来达到一个很好的性能;如果你很无耻地用了巨多的大图片的话,在低显存的电脑上运行你的游戏的时候,你的游戏必然会挂掉。倒是没有必要在图形编辑软件中调整贴图的大小。你可以在unity导入贴图的时候进行调整。

n 不要使用低质量的图片。 在小播放界面的游戏中使用低质量的jpeg图片或者低色彩的png图片亦或是gif图片没什么问题。在发布游戏的时候,引擎会自动压缩这些图片,多重压缩和解压将会降低图片的质量,所以最好保持贴图文件的分辨率为原始分辨率。这样就会减少多重压缩和解压所导致的图片失真现象。


音频

n 使用.ogg格式的压缩音频文件。 所有其他的音频格式文件在发布时将会被转储为未压缩音频文件。

n 对于小音效使用未压缩音频文件。 Unity在运行过程中会解压所有的ogg文件。它会把经常播放的音效转储为WAV或者aiff格式的文件,这样就可以不用cpu总是解压这些文件了。比如快速的枪声,脚步声和其他一些连续播放又很短小的音效。



物理

n 每一个刚体都需要大量运算,所以刚体越少越好。 当角速度和移动速度降低到某个临界值的时候,刚体将会进入休眠状态。当刚体进入休眠状态时,他们需要的运算量将会大量减少,但是会保留很少的一部分运算来随时应对外部的作用力或者物体的碰撞。

n 多重碰撞相比一个接一个地碰撞将会花费更多的运算。 比如一个球去碰一堆球所需要的计算量会远远大于去一个一个地碰这些球所需要的计算量。



Shaders

n 多重效果的shader就比看起来样式很单一的shader要更耗费资源。 同样在一个拥有贴图和光反射的物体上,使用VertexLit Diffuse shader无疑是最省资源的。


脚本

n 选择适当的算法。 选择一个正确的算法将会更容易进行优化。最好的算法不一定就是算法复杂度最低的算法。

n 尽量不要使用FixedUpdate()函数。 这种函数在每一个物体的每一个脚本中每秒调用50-100次。如果可以的话尽量把这个函数里面的东西放在Update()函数中执行。

n 如果可能的话,在脚本无用的时候禁用它。 比如有一个敌人在数千米开外的位置,完全可以禁用它的AI脚本,直到需要的时候再启用这个脚本。启用和禁用物体的最好方法就是使用gameObject.SetActiveRecursively(false)函数,并且把物体的球碰撞和盒碰撞都置为trigger。

n 如果不需要Update函数的时候就删掉它。 在创建一个新脚本的时候,系统会自动加入一个空的Update函数,如果你不使用它的话就把它删掉。

n 适当的时候使用物体引用。 如果调用一个物体需要走一个很弯的逻辑,比如someGameObject.transform.gameObject.rigidbody.transform.gameObject.rigidbody.transform,这样就不如直接在脚本中声明一个变量,把要调用的物体直接赋给这个变量。

n 尽量使用协同函数。 协同函数开销很小,相比于一直在进行不必要调用的Update函数来说更好用。举例来说,如果你有一个控制灯光渐明渐暗的脚本,你就完全可以使用协同函数来替代Update函数。这样的话,在大多数时间灯光不变化的时候,系统的开销会很小。如果这一过程是在Update函数中执行的话,Update函数会一直检测是否需要执行渐变。

n 尽量不要使用搜索物体的函数。 比如GameObject.FindByTag()和 GameObject.GetComponent(),搜索组件的函数也一样尽量少用。搜索就等于遍历,搜索一次物体就要把所有物体都遍历一遍,这个开销我不说大家也应该都明白。尤其要注意,不要在Update()和FixedUpdate()中使用搜索函数,如果需要的话,最好在Start函数中使用变量来获取一次,之后调用就直接用这个变量。

n 尽量不要使用SendMessage()函数或者类似的函数。 SendMessage()函数的执行速度至少比直接调用一个function慢100倍,随着脚本和函数的增多,这个速度会更慢,所以如果能直接调用函数的话就直接调用。

n 关于JavaScript(Boo)中的动态类型。 在使用JavaScript时,声明变量的尽量明确指定它的类型。

2018-06-08 10:49:43 s1314_JHC 阅读数 1662
  • Unity3D场景优化算法

    该课程主要是针对密集型场景裁剪处理提供了解决方案,利用四叉树或者八叉树对场景进行分割,然后通过角色身上的包围盒与四叉树或者八叉树分割的物体进行碰撞检测,这样就可以把玩家周围的物体显示出来,这个也是针对移动端的解决方案。如果对于PC端可以使用多线程分块解决,该课程也是给读者提供了一种场景优化的解决方案。

    126 人正在学习 去看看 姜雪伟
本篇博客作为收尾,介绍探针(重点是反射探针)以及一些后期处理与优化方式。
传送门:
Unity3D灯光与渲染学习之(三):探针使用、后处理与批处理

7.探针的使用

7.1 灯光探针(适用于运动物体),覆盖整个场景,运动物体在覆盖的场景进行移动时,能实时改变运动物体的颜色信息。这方面由于暂时不需要使用,并未过多学习,可以参照PassionY的博文https://blog.csdn.net/yupu56/article/details/76176338
7.2 反射探针(适用于室内场景,相当于一个全景摄像机),将对当前物体有影响的信息保存并体现在物体上。
导入Reflection Probe资源包,找到Scene1场景文件,打开如下图所示。(下载地址(包括第8节的后处理资源):https://download.csdn.net/download/s1314_jhc/10466588

创建新材质赋给小球,并设置为全反射。

为小球添加反射探针(Light > Reflection Probe),可以看到反射探针有一个区域,只有区域内的物体能影响反射探针

现在只反射的是天空盒,原因是Inspector面板中设定了它的type为Baked,即只反射游戏中的静态物体。因此将两个Cube设置为Static即可。再稍微移动下反射探针,即可看到效果。如上右图所示。

对于动态物体而言,首先将灯光探针的type修改为RealTime(比较费效率),并将Refresh Mode设置为每帧。并将反射探针设置为小球的子物体,即可在小球移动时正确显示效果。

8.后处理(Post-Processing)

导入Post Processing Stack资源包,该资源包包括各种对环境的后处理功能,下载资源中也在探针处一并包括(这块内容比较繁琐,之后整理补充)。

9.批处理

在屏幕上渲染物体,引擎需要发出一个绘制调用来访问图形API。每个绘制调用需要进行大量的工作来访问图形API,从而导致了CPU方面显著的性能开销。因此Unity在运行时可以将一些物体进行合并,从而用一个绘制调用来渲染他们。这一操作,我们称之为“批处理”。一般来说,Unity批处理的物体越多,就会得到越好的渲染性能,下图中的Batches就是批处理的数目。

可以批处理的物体:
只有拥有相同材质的物体才可以进行批处理。因此,如果你想要得到良好的批处理效果,你需要在程序中尽可能地复用材质和物体。如果你的两个材质仅仅是纹理不同,那么你可以通过纹理拼合操作来将这两张纹理拼合成一张大的纹理。一旦纹理拼合在一起,你就可以使用这个单一材质来替代之前的两个材质了。比如下图展台的玻璃盖部分,这么做可以提升场景的流畅度(即上图中的FPS)。

批处理分为动态和静态两种。

9.1动态批处理

如果动态物体共用着相同的材质,那么Unity会自动对这些物体进行批处理。动态批处理操作是自动完成的,并不需要你进行额外的操作。批处理动态物体需要在每个顶点上进行一定的开销,所以动态批处理仅支持小于900顶点的网格物体。

9.2 静态批处理

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


2018-02-17 14:27:49 qq_39574690 阅读数 448
  • Unity3D场景优化算法

    该课程主要是针对密集型场景裁剪处理提供了解决方案,利用四叉树或者八叉树对场景进行分割,然后通过角色身上的包围盒与四叉树或者八叉树分割的物体进行碰撞检测,这样就可以把玩家周围的物体显示出来,这个也是针对移动端的解决方案。如果对于PC端可以使用多线程分块解决,该课程也是给读者提供了一种场景优化的解决方案。

    126 人正在学习 去看看 姜雪伟

一、烘焙灯光

      选中灯光物体,在Light组件中设置Mode参数为Baked,然后点击Window-Lighting-Settings,在Lighting面板中点击最下方的Generate Lighting按钮即可实现烘焙。烘焙是为了使Unity无须实时为灯光做工作而优化的一种方法,相当于给周围环境贴上一张灯光效果的贴图。这样就能够提升FPS,减少阴影数量Shadow caster.

当出现CPU bound(CPU超负荷导致卡顿)时,我们可以通过减少不必要的细节物体、利用摄像机远剪辑面减少呈现的物体、遮挡剔除以及LOD等技术来解决该问题。原因是减少了CPU向GPU发送指令的次数。

二、静态批处理

    选中要进行批处理渲染的物体,在Inspector面板的Static下拉列表,打开后选中Batching Static,然后检查Edit->Player Settings->Player->Static Batching打√,还有一个是Dynamic Batching动态批处理,这个最好也勾上。

    运行游戏后,可以打开Window->Profiler->Rendering 检查Draw Calls是否减少了,减少了就说明优化了。完全没有静态批处理的物体的话,物体渲染工作全部交给动态批处理来完成,动态批处理是Unity自己做的工作,不用我们管,而且基本是一个渲染处理一个Calls的模式,这样会导致CPU空闲,GPU忙碌,从而产生CPU等待GPU这段空闲时间,产生了所谓的“卡顿”现象,也叫“失帧”,在直观理解是FPS会降低。(FPS越低越不好)

 静态批处理是消耗内存来达到减少DC的,在手游可能会不常用。

三、减少不必要的细节物体

在复杂场景中,最简单减少DC的方法就是直接删除影响不是很大的细小物体。

四、利用摄像机远剪辑平面减少呈现的物体(视椎体剔除)

我们可以通过调整Clipping Planes的Far数值(从摄像机到远剪辑平面的距离),适当地调小Far,并用Fog雾来掩饰远处物体的隐藏即可。

五、遮挡剔除(有问题)

    遮挡剔除也叫遮挡视图:当摄像机在Occlusion范围内,会将摄像机可视范围之外的物体不进行渲染 以及 在一个大物体后面的物体也不会进行渲染,即不可视物体将不会进行渲染。

  将要遮挡的物体全部选中,然后选择Occluder Static之后,在Window->Occlusion Culling-Bake,Bake之后选择摄像机图标,然后场景中只有这个摄像机可以看到的物体会被渲染出来。物体越多越有效,注意摄像机进入黄色区域才会产生遮挡剔除。

但是经测试只在这种模式下才会产生作用,如下图:

(选中Occlusion的Visualization进入Occlusion模式)

在运行时,不会产生任何作用(Unity 2017.1.1f1版本),进入Frame Debug编辑器观察详细渲染帧情况,与不使用遮挡剔除的情况一致,也就是说遮挡剔除并没有生效。

六、LOD Group

给一个空物体加上一个LOD Group组件

在LOG Group上有4个颜色,绿色 紫色 蓝色 红色

在每种颜色上都设置一个模型Prefab,绿色最精细的模型,红色是最粗糙的模型。(红色一般都不用设置了因为看不到)

可以设置每个颜色区域的百分比。

这个LOG Group可以让摄像机看到的物体根据距离改变物体的不同形态,例如:精细形态、一般形态、粗糙形态,我们在离物体近的时候,就显示精细形态,所以绿色放一个精细的预制体,离物体越远就不用摆放那么精细了。这样来优化性能。

这个需要美工配合的,也就是说一个物品需要做出以上四种形态。

七、自定义遮挡剔除

用自定义脚本来禁用掉在视野之外的物体,特别是带Renderer的物体。

八、Skinned meshes

SkinnedMeshRenderers用于通过使用一种称为骨骼动画的技术对网格进行变形来实现动画。渲染蒙皮网格可能是一个昂贵的操作。如果我们可以在Profiler窗口中看到渲染皮肤网格会导致游戏CPU受限,我们可以尝试做以下几件事来提高性能:

  • 例如,我们可能导入了一个使用SkinnedMeshRenderer组件的模型,但实际上我们并没有对其进行动画处理。在这种情况下,用MeshRenderer组件替换SkinnedMeshRenderer组件将有助于提高性能。
  • 在模型网格中使用更少的顶点可以减少必须完成的工作量。
  • 在某些平台上,剥皮可以由GPU而不是CPU来处理。如果我们在GPU上有很多容量,这个选项可能值得尝试。我们可以在Playing Settings - Others 设置中为当前平台和质量目标启用GPU剥皮。

九、尽量避免在主线程上(Unity生命周期方法)处理非渲染任务

假设:主线程上需要渲染100个物体,同时还要处理一些与渲染无关的事情,可以将与渲染无关的事情如计算数据,放到非主线程处理,尽可能地减少主线程的负荷,从而避免CPU bound。

CPU bound 总结:

CPU bound 是指 在一次渲染中,CPU拖了GPU的后腿,CPU频繁地向GPU发送命令,产生大量的SetPass调用(DC),导致CPU超负荷,造成游戏卡顿、失帧(原因:GPU空闲),一个不卡的游戏,其CPU和GPU的工作是双方都很流畅地工作的。

为了减少SetPass调用,可通过如下三种方法:

① 可以减少渲染的物体数量

可参考上面的三、四、五、六、七章节介绍

② 减少每个物体照明、阴影、反射渲染的次数

可参考上面的第一章节介绍,烘焙阴影、反射探针等技术来减少,即多采用静态的东西,而不是实时动态的。

③ 使用批处理 和 合并物体Mesh减少批处理次数

可参考上面的第二章静态批处理介绍,合并物体Mesh可以看本人博客文章 有介绍

④ 使用图集减少DC

 https://blog.csdn.net/cjsen/article/details/52487706?utm_source=copy#commentBox

 

GPU bound 总结:

GPU bound :在一次渲染中,GPU拖了CPU后腿,一般是GPU(渲染管线)处理大量的数据不够迅速导致。

① Fill rate 填充率

填充率是指GPU每秒可以渲染到屏幕上的像素数。如果我们的游戏受填充率的限制,这意味着我们的游戏试图绘制更多的像素每帧GPU无法处理。

检查是否是GPU填充率过低导致GPU bound的,可以通过将Game窗口的分辨率调低,再次进行性能测试得知,若有明显改观,可能是Fill rate问题。

可通过优化着色器(shader)来减少游戏每帧所需绘制的像素数量,例如:本身使用的是内置着色器,可用带"mobile"的着色器进行替代 或 其他合适的着色器进行替代,只要确保在视觉保真度基本不变的情况就可以适当地选取合适的着色器,进行减少游戏所要求渲染的像素数量。

若是自定义着色器,则需要专业的shader人员进行优化片元着色器fragment。

② Overdraw 重复绘制

Overdraw是指同一个像素被多次绘制,当物体与物体重叠时会发生,如:UI重叠、为着色的颗粒、透明材料。

③ Image Effects 图像效果(这个有点懵逼)

使用图像效果可以大大提高填充率问题,特别是如果我们使用多个图像效果。如果我们的游戏使用了图像效果,并且正在与填充率问题作斗争,我们可能希望尝试不同的设置或更优化的图像效果版本(如Bloom(优化)代替Bloom)。如果我们的游戏在同一个相机上使用多个图像效果,这将导致多个着色器通过。在这种情况下,将图像效果的着色器代码合并到一个单一的通道中可能是有益的,例如在Unity的后处理堆栈中。如果我们优化了图像效果,但仍然存在填充率问题,我们可能需要考虑禁用图像效果,特别是在低端设备上。

相关参考文献:英文-官方文档说明(比较详细)

代码实现静态批处理

PS:这个不能超过65000个顶点,需要自己处理

public static void Combine(GameObject[] gos, GameObject staticBatchRoot);

将staticBatchRoot下的子物体们gos用静态批处理的方式进行优化处理,减少Batch次数。
重要提示:只有具有相同材质的对象才可以批量处理,因此尽可能多地共享纹理/材质是很有用的。

staticBatchRoot可移动,其子物体们不可移动

第一个参数gos是staticBatchRoot下的子物体GameObject数组

2017-04-26 13:41:12 qq_33747722 阅读数 10313
  • Unity3D场景优化算法

    该课程主要是针对密集型场景裁剪处理提供了解决方案,利用四叉树或者八叉树对场景进行分割,然后通过角色身上的包围盒与四叉树或者八叉树分割的物体进行碰撞检测,这样就可以把玩家周围的物体显示出来,这个也是针对移动端的解决方案。如果对于PC端可以使用多线程分块解决,该课程也是给读者提供了一种场景优化的解决方案。

    126 人正在学习 去看看 姜雪伟

本文使用Unity5.x版本,由于Unity4.x到Unity5.x更换了光照引擎,所以本文内容只适合于Unity5.x版本

本文向大家介绍Unity烘焙动态光照来实现光源优化

什么是动态光源?

Unity灯光默认是实时光照,也就是说物体在灯光下不同位置产生不同灯光灯光效果

什么是烘焙动态光源?

由于动态光源在实时光照下会大量的Setpass Calls(Draw Calls)

为了减小Setpass Calls,我们烘焙动态光源

将该场景灯光效果烘焙,原理是Unity为我们自动生成光照贴图

这样大大减少了Setpass Calls

 

接下来我详细介绍下,在Unity实现烘焙动态光照

新建场景,在场景中创建如下对象

下图是对象结构列表

此时我们运行游戏,发现Setpass Calls比较大(手游一般控制在60一下)

我们目标是烘焙光照贴图,实现减少Setpass

我们将Cube设置为静态对象(烘焙贴图)

选中全部点光源,将Baking选择为Baked

Realtime: 实时(默认)

Baked: 烘焙

Mixed: 混合

打开Window->Lighting

勾选中Baked GI

点击Build烘焙(也可以勾选Auto,自动更新)

此时在Lightmap窗口中会发现已经生成了光照贴图

此时运行游戏观察Setpass Callls发现大大减少

细心的同学可能发现,烘焙后的场景“变亮”了,无伤大雅,因为用户在体验游戏不会感觉出来有什么不一样

但是实现了烘焙,会场景中的主角不再受到光照影响

这是因为我们此时是光照贴图影响这场景的显示,灯光不再实时光照了

有什么方法可以解决呢?

接下来介绍Light Probe Group(探针)

Light Probe Group作用是记录该位置光照信息

按下图创建Light Probe Group

创建多个探针

重新烘焙(勾选了Auto下不需要)

此时在减小了Setpass Calls情况下依旧可以“实时光照”,达到优化目标效果

Light Probe Group的位置摆放的好话,基本可以达到和实时光照效果一样

 

如果本文对你有帮助,请多多支持,干货满满,欢迎前来阅读!!!

 

 

 

 

 

 

 

没有更多推荐了,返回首页