执行顺序
本文重点介绍 UNIGINE 执行序列的细节。在这里,您会发现 UNIGINE 引擎背后发生的事情。有关 UNIGINE 工作流程的高级概述,请参阅引擎架构文章。
UNIGINE 引擎的内部代码和你的应用逻辑可以使用以 C++ 或 C# 编写的插件进行扩展,以预定义的顺序执行:
- 初始化.在此阶段,准备并初始化所需的资源。一旦这些资源准备好使用,引擎就会进入主循环。
主循环.当UNIGINE进入主循环时,它的所有动作可以分为三个阶段,在一个循环中一一执行:
当应用程序运行时,这个循环每帧重复一次。
- Shutdown。当 UNIGINE 停止执行应用程序时,它会执行与应用程序关闭和资源清理相关的操作。
下图(可点击)表示默认 Async Rendering 物理模式下 UNIGINE 执行序列的主要阶段。
等待 GPU#
大多数情况下,UNIGINE 在主循环中完成其所有阶段的速度比 GPU 实际渲染帧的速度要快。这就是使用双缓冲的原因:它可以通过交换执行渲染的 GPU 缓冲区(后部和前部)来更快地渲染帧。
当所有脚本更新完毕,CPU 上的所有计算都完成后,GPU 仍在渲染 CPU 上计算出的帧。因此,CPU 必须等到 GPU 完成渲染帧并交换渲染缓冲区。这种等待时间的周期由表中的 Waiting GPU 计数器表示性能分析器.
如果 Waiting GPU 时间太高,则可能表示存在 GPU 瓶颈,需要优化艺术内容。但是,如果帧速率一直很高,则意味着您仍有可用的 CPU 资源来处理更多数字。
从所有脚本更新完成,CPU上的所有计算都完成,到GPU渲染完帧的那一刻,经过了多少时间,还取决于是否启用了垂直同步(VSync)(可以通过系统菜单)。 如果启用了垂直同步,CPU 将等待 GPU 完成渲染并执行垂直同步。在这种情况下,Waiting GPU 计数器值会更高。
下面的四种方案显示了禁用和启用 VSync 的 CPU 和 GPU 性能的不同场景。
前两个方案显示了禁用VSync 时帧的计算和渲染(在这两种情况下,监视器垂直回扫都被忽略):
- 方案 1. CPU 计算帧的速度比 GPU 渲染它的速度快。因此,CPU 等待 GPU(Waiting GPU 时间很高)。
- 方案 2. CPU 计算的执行速度比 GPU 渲染帧的速度慢。因此,GPU 必须等待 CPU 完成计算。在这种情况下,Waiting GPU 时间很小。
方案3和方案4显示了启用VSync时帧的计算和渲染(考虑了监视器垂直回扫):
- 方案 3. CPU 计算帧的速度比 GPU 渲染速度快,CPU 等待 GPU。 但是,在这种情况下,CPU 和 GPU 也都在等待 VSync。
- 方案 4. CPU 计算帧的速度比 GPU 渲染它的速度慢。在这种情况下,GPU 不仅要等待 CPU 完成计算,还要等待 VSync。
物理和寻路线程#
引擎使用所有可用线程同时更新可见节点和多线程物理(在异步物理更新模式)和与渲染阶段并行更新的寻路。
以下方案说明了在启用 Async Rendering 物理模式的情况下计算和渲染帧过程中的线程:
第一个物理帧与主线程中的渲染并行计算。然后所有其余的物理帧都在主线程中更新。所有客户端的代码,例如 updatePhysics(),也在主线程中被调用。
最后两个方案说明了如何在 Before Rendering 模式下更新物理:
在这两种情况下,CPU 或 GPU 都必须等待彼此完成其渲染并交换同步。
渲染和物理帧率之间的相关性#
渲染帧率通常会有所不同,而正如我们之前已经提到的,物理模拟帧率是固定的.这意味着来自世界逻辑的 update() 和 updatePhysics() 函数以不同的频率被调用。
上图描述了当物理帧率固定为 60 FPS,渲染帧率变化时会发生什么。一般来说,有以下三种可能的情况:
- 渲染帧率要高得多。在这种情况下,对两个或更多帧进行一次物理计算。这不会引起任何问题,因为在计算之间插入了移动对象的位置。 Stable FPS模式默认开启,避免跳帧和掉帧(详见下节说明)。
- 渲染帧率相同或几乎相同。这种情况也可以,每帧计算一次;物理与图形保持同步,反之亦然。
渲染帧率要低得多。这就是问题开始的地方。首先,正如您从图片中看到的,每帧应计算物理两次甚至更多次,这不会加快整体渲染过程。其次,您不能将物理帧率设置得太低,因为在这种情况下,计算将失去太多的精度。
稳定的 FPS#
当应用程序的渲染帧率高于物理更新时,某些具有物理更新的帧将需要更多时间来计算。这会导致应用程序的帧率跳跃和下降,从而导致模拟不稳定(尤其是涉及输入和交互性)。
为了使帧率更稳定,默认启用 Stable FPS 功能。如果当前帧花费的时间少于前一帧(通常是由于缺乏物理计算),它会添加一个 Idle 状态。这确保每一帧花费相同的时间有效地消除帧率的脉动。
如果您的应用程序用于机器学习或抓取帧序列 (Video Grabber),而平滑度并不重要,您可以关闭此功能。
将引擎帧率与物理帧率同步#
如前所述,如果引擎帧率高于物理帧率,则物理计算的结果会在帧之间进行插值。但是您可以通过将引擎帧率同步到物理帧(通过代码设置 SyncEngineUpdateWithPhysics 标志)来计算每个渲染帧的物理。在这种模式下,如果物理对象具有非线性速度,则不会发生抽搐。如果引擎 FPS 低于物理 FPS,则此标志无效。