智慧 + 毅力 = 无所不能

正确性、健壮性、可靠性、效率、易用性、可读性、可复用性、兼容性、可移植性...

导航

Unreal Engine 4 性能优化工具(Profiler Tool)

Posted on 2017-10-25 10:52  Bill Yuan  阅读(2014)  评论(0编辑  收藏  举报

转自:http://aigo.iteye.com/blog/2296548

Profiler Tool Reference

https://docs.unrealengine.com/latest/INT/Engine/Performance/Profiler/index.html

 

原文:

https://www.unrealengine.com/zh-CN/blog/how-to-improve-game-thread-cpu-performance

 

您游戏中的帧频率是不是太低? 您了解为什么会发生这种现象吗? 这是不是由于您同时生成了太多敌人?还是由于某个特定敌人过于消耗系统资源? 是由于您设置了过多的视觉特效,还是由于您所设计的战斗系统所造成的?

放松一下,不要一下子就得出结论!

尝试修复任何性能问题的第一步是收集信息,这样您可以做出明智的决策,以确定下一步该怎么做。 有些人会很自然地说这样的话“当然慢啦! 这个关卡有100,000个actor耶!”,但如果您没有收集适当的数据,您可能就会尝试在关卡中花费大量时间来降低actor的数量,而没有尝试修复真正造成性能表现瓶颈的问题,这些问题可能是完全无关的问题,而且修复起来要容易得多。

明白! 可是从哪里开始着手呢?

您要采集的第一份数据是需要了解,您的性能瓶颈到底是出现在游戏线程中、在渲染(描画)线程中、还是出现在GPU中。 要了解具体原因,您需要以非调试版本来启用游戏,然后输入控制台命令“stat unit”,从而显示完成各项任务需要花费多少时间。

您的时间指的是生成游戏中每一帧所需要花费的总体时间。 由于在完成一帧前会同时同步游戏和描画线程,时间常常接近于这些线程中的时间。 GPU时间衡量的是显卡需要多长时间来渲染场景。 由于GPU时间与帧同步,它的值很可能也类似于时间。

如果时间非常接近于游戏时间,那么您的瓶颈是游戏线程。 如果时间非常接近于描画时间,那么您的瓶颈是渲染线程。 如果两者都与GPU时间不怎么接近,那么您的瓶颈就是显卡。

本文中,我们仅仅讨论如何处理游戏线程中的问题。

哇!现在我知道游戏的瓶颈是游戏线程啦、 接下来怎么做?


查看游戏线程的性能表现的最佳工具是使用统计数据分析程序。 您可以在控制台输入“stat startfile”来启用分析,您可以按下键盘上的波浪键 (~)来打开控制台。 让我们至少运行10秒左右,这样可以获得许多帧间的良好平均值。 更长的分析时间也很好,而且我们可以使用它们来检测间隙时间较长的问题,但一般不推荐让分析时间超过30分钟,因为这样文件就太大了。 当您获得良好的时间样本后,您可以输入“stat stopfile”来终止分析。 在路径Saved/Profiling/UnrealStats下,会有关于您项目文件夹的ue4stats文件。

好的,我进行了分析。 我该如何打开这个分析文件?

如果需要打开您捕获的分析文件,您必须使用UnrealFrontend(虚幻前端),它和UE4Editor位于同一个文件夹,或者您也可以打开窗口菜单中的编辑器的Session Frontend(会话前端)选项卡。 当您打开了会话前端选项卡后,您需要切换到Profiler(分析程序)的小选项卡。 在该处,您可以选择载入您最近捕获的ue4stats分析文件。

我现在打开了分析文件,我现在应该查看哪些数据?

很重要的信息就是位于底部的功能树。 展开GameThread(游戏线程)项目,然后往下拉,直到您看到超过几毫秒的“Inc Time”(包含时间)条目,而且其不包含许多子项或不包含任何子项。 同时关注一下“Calls”(调用)数列,它显示了每帧调用的统计数据的平均次数。 不要被“CPU Stall”(CPU停滞时间)项目弄糊涂了。 它们显示的是线程等待处理其他内容时所花费的时间,所以不是主要数据,而且仅仅会在帧频率受限或者游戏进程不为瓶颈时才会显示出来。 在下方的分析数据中,我们发现了存在问题的字体缓冲时间。

这是本周在Fortnite中发现的真正问题! 在本例中,我们显示了基于相机和重要游戏对象间距离而变换大小的许多文本。 由于我们在每一帧都对文本调整大小,所以在Slate和虚幻引擎用户界面系统中的字体缓存中充满了上百个相同的字符串。 修复的方法是停止基于距离来动态缩放文本,也可以根据特定间距的阀值来分别变更文本大小。

这个方法对于Fortnite很好用,但我出现的问题不是“字体缓存”。

您需要关注一些固定的需要注意的数据。

其中一个重要的项目是FTickFunctionTask。 此项目下是正在更新的每个actor和组件。 一般来说,降低每帧更新的actor和组件的数量都可以很好地加速游戏。

如果您的游戏中存在着应永不更新的actor并且您正在使用C++代码,您可以将其放置在actor的构造函数中,以完全防止其更新:

PrimaryActorTick.bCanEverTick = false;

如果actor仅在某些时候进行更新,您可以转而将其放置在构造函数中:

PrimaryActorTick.bCanEverTick = true;

PrimaryActorTick.bStartWithTickEnabled = false;

然后您可以使用SetActorTickEnabled函数来启用和禁用更新。

另一个要关注的是BlueprintTime(蓝图时间)。 找到这个值的最佳方法是切换到包含(合并)视图并在列表中找到它。 这样就可以把所有的BlueprintTime(蓝图时间)条目组合到单一行中。 如果您选择BlueprintTime(蓝图时间),然后切换回层次视图,则其会选择所有蓝图代码被执行的位置,这样能让您很好地了解花费时间进行处理的位置及其位于哪个蓝图中。

另一个常见的问题位置是TickWidgets(更新控件)。 如果这个统计数据值很高,这表示您可能同时显示了太多控件,或者这些控件上的属性代理过于复杂。 一些slate属性,比如可见性,可能会在每帧被调用好几次,这样它们的值必须要小而且能及时返回。

您是不是在游戏中有很多骨架网格物体? SkinnedMeshComp更新时间有时也会消耗很多系统资源。 请尝试降低显示在分析文件中的骨架中的骨骼数量,或者降低动画蓝图的复杂度。 如果您不需要在无法看到骨架网格物体时更新动画,请考虑将骨架网格物体组件上的MeshComponentUpdateFlag(网格物体组件更新标识)正确设置为OnlyTickPoseWhenRendered(仅在渲染时更新姿势)。 请注意,将此标识设置为AnimNotifies(动画通知)将使得这些网格物体不被渲染时不再对其进行触发。

实际上,我正在查找为何游戏不断地产生卡顿。

最好的方法是寻找时间轴中出现的顿卡,选择其周围的帧,然后将视图变更为“最大“,而不是“平均“。 这样会变更所有数字,从而在选择的帧数范围中显示峰值,而不是显示平均值。

谢谢!

对总体游戏性能来说,使用分析程序是很关键的。这样可以通过防止您因无法了解真正的问题而过度猜测。 如需了解分析程序中所有功能的更多信息,请访问我们的文档页面。https://docs.unrealengine.com/latest/INT/Engine/Performance/Profiler/index.html