在使用虚幻4做项目的过程中性能┅直是不可忽视的话题为了画面效果我们至少需要每秒20帧左右。根据不同的项目要求这个帧数可以能要40或者60甚至在某些情况下会要求哽高。
本文根据官方文档博客等综合而来意在发现问题所在更高效的解决问题,下文将根据CPU,GPU来分析
·首先要确定我们的性能瓶颈出现在哪里,这时我们在控制台输入“stat unit”它会显示如下图所示:
也可以通过视图显示出来
这里Farme有两个度量:
第一个是这个帧的当前帧时间(左)
第二个是在最后几秒的最差帧时间(右)
左侧的图是游戏、绘图和GPU的几个帧里的帧时间图。
Frame时间是产生一帧花的总时间注意GPU和CPU是同时執行的,所以帧花费的总时间不是它们时间的总和但是任一项拖了后腿都可能是帧率降低的原因。游戏的实际单帧时间由这三者之一限淛:Game(CPU 游戏逻辑线程)Draw(CPU 渲染线程)或者 GPU(GPU)。 您的帧时间指的是生成游戏中每一帧所需要花费的总体时间
由于在完成一帧前会同时哃步游戏和描画线程,帧时间常常接近于这些线程中的时间 GPU时间衡量的是显卡需要多长时间来渲染场景。 由于GPU时间与帧同步它的值很鈳能也类似于帧时间。
游戏逻辑线程):这是一个任意的CPU逻辑它不与渲染直接关联。如果该组很慢通常的情况是程序员有需要修正的內容,但是它可以是与美术相关的比如:屏幕上有太多颗粒。内置在CPU分析器中的Frontend工具可以用来研究CPU性能并且观察正运行缓慢代码特定嘚、与复杂任务相关的游戏设置只能在CPU上执行,像A.I.和Navigation的设置
Draw(绘图) :这是一个与GPU上渲染设置相关的CPU逻辑。它包括图形API和绘图调用的设置或者如果渲染代码已经以非最佳的方式修正了,它就可能与渲染代码相关
GPU :GPU渲染帧花费多长时间。它包括:执行图形API调用、绘图调鼡、着色器和后过程着色器的执行、获取纹理……这里的问题通常与资源相关它可能是场景中类似着色器这样非常复杂的东西,或者场景中有许多不同的网格结果就是每帧中发生太多的绘制调用。这可能会让一个专业美工或程序员找到问题根源但是通常情况下需要一些决策——为了达到预期性能,应该做哪些权衡这里能帮到您的最棒的工具是GPU分析器和着色器复杂性视图,这些会在之后进行讨论同時下面还会讨论“Advance”目录中显示的特定stats。
如果一帧花的时间跟逻辑线程的时间比较接近那么瓶颈在逻辑线程,相反如果跟渲染线程的时間比较接近那么瓶颈在渲染线程。如果两个时间 都不接近但跟GPU时间比较接近,那么瓶颈在显卡上图中我们可以看到 GPU 是限制主因(三鍺最大的一个)。为了取得更少的 单帧 时间在这个情形下必须先优化 GPU 的负载。
(1) 为确保引擎中最大的帧速没有被限制先设置下帧率(- r.VSync鈳以关闭垂直同步):
PrePass / Depth only pass: RenderPrePass / FDepthDrawingPolicy 渲染遮挡物,对景深缓冲区仅输出景深该通道可以在多种模式下工作:禁用、仅遮蔽,或完全景深具体取決于活动状态的功能的需要。该通道通常的用途是初始化 Hierarchical Z 以降低 Base 通道的着色消耗(Base 通道的像素着色器消耗非常大)
Lighting : 阴影图将对各个光照渲染,光照贡献会累加到场景颜色并使用标准延迟和平铺延迟着色。光照也会在透明光照体积中累加
Fog : 雾和大气在延迟通道中对不透明表面进行逐个像素计算。
几个值得注意的数据项:
检查影响GPU效率的内容查看有无超标现象
比如分辨率、HMD SP、投影贴图大小
1:basepass消耗高的话就需要了解下哪些模型,贴图材质开销太大。 面数过高的模型就减面;半透明用的多的物件就斟酌下是否必要;材质是GPU消耗過高的一大元凶比较耗的材质可以检查下节点,关闭一些非必要的效果材质复杂程度在这里可以查看,越红的越消耗原则上减少使鼡点动画和曲面细分等一些效果。
红色:意味着性能消耗非常高 绿色:意味着性能消耗最低半透明:意味着增加性能消耗
可在材质里查看着色器的说明数量尽可能减少
另外场景里摆放的模型如果不需要参与碰撞计算的话,最好关闭碰撞减少运算消耗。
游戏运行时在控淛台里使用showflag(隐藏)命令可以帮我们快速定位具体是模型特效?光照等等哪个消耗高,消耗高的就优化列举几个常用的”showflag.”命令“0”关闭“1”打开:
ScreenSpaceReflections: 切换屏幕空间的反射效果,可能会非常影响性能对那些达到一定粗造度的像素有效
DynamicShadows: 切换所有的动态阴影(阴影贴图的渲染,以及阴影的过滤和投影)
Decals: 切换贴花渲染
Tessellation:切换曲面细分(仍将运行曲面细分 shader但生成更多三角面)
IndirectLightingCache: 切换是否动态粅体或者静态物体具有使用间接光照 Cache 时无效的光照贴图。
Bounds : 显示编辑器中当前选中物体的边界框
VisualizeSSR :屏幕空间反射像素显示为亮橙色是計算较慢的区域
关闭stuff查看效率
r.VSync 开启/关闭垂直同步(可能依赖于是否原生全屏)。
r.SeparateTranslucency 这是一个用于修复半透明情况下景深的问题的功能如果鈈需要的时候可以把它关闭,并有其他影响(查阅 SceneColor)
FX.AllowGPUSorting 禁用粒子排序(在大量粒子的使用可以妥协使用)。
r.ScreenPercentage: 用于减小内部实际渲染分辨率画面会在重新放大
r.ShadowQuality: 移动端Stationaary灯光动态阴影质量,调整其值查看帧速变化以判断瓶颈
r.Shadow.MaxResolution: 移动端Movable灯光动态阴影质量,调整其值查看帧速变化以判断瓶颈
StatMemory:提供关卡中内存使用情况
2:灯光消耗高的话,需要检查动态光照数量(固定光也可以投射动态光照)是否有過多重叠的照射区域,照射范围参数是否开的太大由于静态光照Build后已将灯光信息存储进了Lightmap,游戏中不再计算所以灯光的主要消耗来自動态光源。先在世界大纲里查看所有灯光类型确定有几盏动态光和固定光,前面有红点的是动态黄点的是固定。
再进一步查看固定光嘚照射范围的重叠部分是否太多重叠的越多,交集处越亮越红用灯的原则是能不用动态光就不用(消耗主要来自被投照射的Mesh),灯光照射范围尽量不重叠且同一个地图里固定光不能超过4盏。
光照复杂度视图模式基于动态光源的数量来对场景进行着色
黑色:意味着没有收到动态光源影响。
不同颜色:从绿到红表示受到动态光源的影响逐步增加。
关闭灯光的投射动态阴影也可以降低一些消耗甚至一些灯咣可以直接关闭投射阴影功能。
3:后期处理是另一个GPU消耗过高的元凶需要慎用,原则是尽可能的把一些不必要的参数关掉尤其是SSR,后期AO,Bloom等一些参数默认会自带一些数值,没必要的全部清零抗锯齿模式切换成FXAA。
这个生成通过光源进行阴影投射的深度数据的pass
作用与这裏的消耗主要受到开启了投影的光的数目、动态光照影响的面数、以及阴影的质量的影响。
如果有大量的材质使用了不同的贴图导致Texture Sample的數量爆炸的话,就会自然的变成瓶颈UE4有使用Texture Streaming,如果存储空间爆炸了的话就会出现贴图模糊的情况,这时候可以使用Stat Streaming指令进行分析
EarlyZPass,對非透明物体进行的早期的深度计算
数据似乎被用于遮蔽计算,如果不使用Dbuffer Decals的话可以关掉但是早期的深度计算可以在BasePass之前进行遮蔽计算,能让basepass以及之后所有的通道的计算减少很多而且即便在这里不进行深度计算,会影响这里的运算量的变量依然会作用与后面的深度计算阶段因此关闭EarlyZPass还是需要多做考虑的。另外要使用DBuffer Decals的话必须使用Opaque and
masked的zpass计算否则应该会出现奇怪的现象。
性能上受到非透明物体的面数的影响同时根据上面的选项不同也受到Masked的材质的影响。
Hierarchical Z-Buffer用于计算HZB遮蔽,同时也会被屏幕空间内的射线演算使用例如屏幕空间反射计算、AO等。同时被用于Mip的设置受屏幕空间的大小影响。据官方描述HZB拥有较高的固定性能消耗,每个物体所造成的消耗较小可以通过r.HZBOcclusion来调整运算的类型。
对非透明的物体进行演算并填充到GBuffer使用缓冲区可视化模式可以在视图中看到效果。几乎所有的延迟渲染都受到其影响洇此才叫基础通道。
rhi指令检查各种贴图和triangle的消耗
另外,前向渲染的光照也在这里进行此时光照的数量也会影响到这里的消耗。
半透明嘚材质以及光照演算通过Stat gpu中的Translucency and Translucent Lighting可以进一步查看。消耗受到屏幕空间大小以及屏幕内的半透明物体的数量影响半透明物体的光照计算要盡量减少过度绘制。以及避免过多的需要进行半透明光照计算的光的数量
粒子模拟,这里只展示GPU粒子的消耗性能主要受粒子数量以及昰否开启了基于深度的粒子碰撞影响。粒子的优化主要通过LOD以及设计上的优化进行
UE4的后期处理功能比较多,AA、DOF、自动曝光以及很多其他嘚功能都在其中每种PP特效都会产生额外的性能消耗,如果使用了PP材质的话其复杂度也会影响性能。
反射捕捉控件的计算缓存可以将显礻模式调整为Reflections来查看各个控件对缓存的影响通常的建议是放一个大范围的低精度反射捕捉,然后在需要的地方尽量不重叠的放置高精度嘚捕捉控件影响性能的主要就是捕捉控件的数量及范围,也受屏幕空间的大小影响
速度主要用于TAA以及Motion Blur,受到移动物体的数量以及其面數的影响主要的优化策略是使用LOD。
屏幕空间反射通过以下连个指令来进行调节:
查看游戏线程的性能表现的最佳工具是使用统计数據分析程序在控制台输入“stat startfile”来启动分析,等10秒左右输入 “stat stopfile”收集这10秒的平均值当然也可以等更多的时间在路径Saved/Profiling/UnrealStats下,会有关于您项目攵件夹的ue4stats文件
也可以用“STAT SLOW”来获取实时的报告,它可以通过报告运行一帧中特定时间段(默认10毫秒)来逐步定位帧停顿的位置
运行速度较慢的数据将会在HUD上显示一段时间,从而判断性能波动“Stat stopslow”来关闭它.
参数以秒为单位(所以10ms也就是0.01秒)参数可设置持续的时间,默认值是 10秒
唎:STAT SLOW 0.01 10这将会渲染在过去的10秒内所有运行时间超过10毫秒的循环统计数据。
现在我们需要分析需要打开编辑器中的Session Frontend(会话前端)
当您打开了会話前端选项卡后,您需要切换到Profiler(分析程序)的小选项卡 在该处,您可以选择载入您最近捕获的ue4stats分析文件
1.这是一个渲染线程vs游戏线程的简圖,根据CPU逻辑与渲染的关系一眼你就会知道你是否是CPU受限的,或者它是否是与游戏相关的且花费最多性能的逻辑
注意这里的CPU停转是CPU闲置等待其它线程结束的时间。
4.如果你在函数时间(3)的层级列表中选择了特定的函数你可以看到这里的显示变化,这里显示了什么函数調用了这个函数以及该函数调用了哪些函数,同时可以看到这些调用和被调用函数执行时间的比例
5.左侧面板展示了stats和stat组。顶层是stat组伱可以展开它查看内部的独立stat。这些stat可以是整型、浮点型数字或者内存你可以控制哪些显示在stat过滤器面板(6)中。如果你鼠标停留在一個stat上会弹出该stat的分析信息(8)。
6.在这里你可以通过搜索想要的stat、改变分组和排序、隐藏/显示不同类型的stat(浮点/整型/内存)以及启用/禁用層级视图控制stat面板的显示(5)
7.这些控件用于显示函数时间的层级列表和所选函数的分解信息(4)
b. 视图模式——这会改变函数时间分层的層级列表视图(3),或者改变单纯的函数列表里面包括这些函数的子程序包括的或排除的时间。
c. 向前、向后按钮可以让你在图像视图的鈈同部分之间跳转(2)所有你可以看到一系列信息,之后缩小你的选择范围直到一个帧然后用这些按钮来在两者之间切换。下拉箭头顯示了之前的选择
d. 这里的火焰按钮是用来展开你当前选择函数的时间层级列表的(3),用来查找花费最多时间的路径它也会用一个小吙焰图标来标识该路径。
8.鼠标在stat面板(5)的一个stat上面停留时会显示关于该stat的分析信息,最重要的是最小值、平均值和最大值:
这里我们呮关注几个选项展开GameThread(游戏线程)项目,然后往下拉直到您看到超过几毫秒的“Inc Time”(包含时间)条目,而且其不包含许多子项或不包含任哬子项 同时关注一下“Calls”(调用)数列,它显示了每帧调用的统计数据的平均次数 不要被“CPU Stall”(CPU停滞时间)项目弄糊涂了。
它们显示嘚是线程等待处理其他内容时所花费的时间所以不是主要数据,而且仅仅会在帧频率受限或者游戏进程不为瓶颈时才会显示出来
还有┅个重要项目TickFunctionTask。 此项目下是正在更新的每个actor和组件 一般来说,降低每帧更新的actor和组件的数量都可以很好地加速游戏
另一个要关注的是BlueprintTime(蓝图时间)。 找到这个值的最佳方法是切换到包含(合并)视图并在列表中找到它 这样就可以把所有的BlueprintTime(蓝图时间)条目组合到单一荇中。 如果您选择BlueprintTime(蓝图时间)然后切换回层次视图,则其会选择所有蓝图代码被执行的位置这样能让您很好地了解花费时间进行处悝的位置及其位于哪个蓝图中。
另一个常见的问题位置是TickWidgets(更新控件) 如果这个统计数据值很高,这表示您可能同时显示了太多控件戓者这些控件上的属性代理过于复杂。 一些slate属性比如可见性,可能会在每帧被调用好几次这样它们的值必须要小而且能及时返回。
您昰不是在游戏中有很多骨架网格物体 SkinnedMeshComp更新时间有时也会消耗很多系统资源。 请尝试降低显示在分析文件中的骨架中的骨骼数量或者降低动画蓝图的复杂度。
如果您不需要在无法看到骨架网格物体时更新动画请考虑将骨架网格物体组件上的MeshComponentUpdateFlag(网格物体组件更新标识)正確设置为OnlyTickPoseWhenRendered(仅在渲染时更新姿势)。 请注意将此标识设置为AnimNotifies(动画通知)将使得这些网格物体不被渲染时不再对其进行触发。
合并多个Actor以及它们的材质和贴图使其转化成Mesh可以减少材质数量和材质复杂程度。
对不同设备设置不同的渲染参数以节省性能
设置顯示细节模式和配置
LOD模型不同细节根据距离参数优化渲染效率
· CSM联级动态阴影
CSM 阴影不会出现调制阴影中的双重阴影,在为多个物体投射陰影时此方法速度较快
CSM使用了额外的纹理采样器,可通过项目设置将其禁用:
线框视图模式可以告诉你场景和独立网格中有多少顶点和彡角形要实现这个模式,你可以在编辑器等级视口的可视化模式菜单中找到:
如果你的网格有三角形/顶点的富余而且远比摄像头的充足时,线框就会变成实线如果你的网格不总是实线的,这意味着你有可能需要比渲染更高的复杂性你就应该减少网格中的多边形数量。
减少三角形和顶点的数量永远都是提高性能的方法但是很多时候,一个单独网格比多个网格刻画集合图形的性能要好得多(一个有1000个頂点的网格可能比10个有100个顶点的网格的更新和渲染都快)这是因为不仅这些网格可能会分别单独调用GPU来绘制,也因为UE4会为每个网格单独保存和更新变换信息而且可能检查这些独立网格间的碰撞。所以如果没有功能性的原因来设置单独网格的话,你应该考虑在把它们引叺UE4之前在DCC工具中选择合并它们
关于合并网格反对的说法是:一个单独的网格可能不能被部分剔除,所以如果它的任何一部分是可见的整个网格都会渲染。由于这个原因可能把你的整个关卡都合并成一个单独网格可能不是一个好主意,但是让每一个三角形都成为一个单獨网格同样也不是最理想的所以在两种极端中取得平衡至关重要。
当三角面密度太高(高到三角面小于2*2像素 往往发生在远处物体上) 很容易出现问题
分别查看三角面、顶点、灯光数量、阴影设置、Actor数量
点动画的Shader处理过于复杂
多重UV、过多的SG
点没有合並、场景GPU粒子模拟数量过多
减少材质Shader的指令的数量。减少Texture Sample的数量:把经常使用到同一个物体上的图案合在一张贴图上;去掉对质量影響很小的贴图比如Specular、AO等。尽量使用QualitySwitchSin, Pow, Cos, Divide, Noise节点。多向量的计算量总是大于单向量的计算量
使用预算可见性剔除遮挡的对象。
当使鼡lightingfunction、IE、接受投影、区域光、复杂shadingmodes的时候会变得更昂贵反射SSR如果有问题,请关掉它另外后期AO也很耗费资源。