Unity3D:分析探查器跟踪

推荐:将NSDT场景编辑器加入你的3D工具链
3D工具集:NSDT简石数字孪生

分析探查器跟踪

分析应用程序时,可能会遇到一些常见问题。本页概述了如何调查一些常见性能问题的原因。

解析启动跟踪

在查看启动时间的痕迹时,有两种关键方法可以检查:和 。这两种方法是项目的配置、资产和代码可能影响启动时间的主要位置。UnityInitApplicationGraphicsUnityLoadApplication

注意:应用程序的启动时间因平台而异。在大多数平台上,启动发生在初始屏幕出现时。

在 iOS 设备上运行的示例 Unity 项目的仪器跟踪
在 iOS 设备上运行的示例 Unity 项目的仪器跟踪

在上面的屏幕截图中,来自在 iOS 设备上运行的示例 Unity 项目的 Instruments 跟踪,在特定于平台的方法中,记下 and 方法。startUnityUnityInitApplicationGraphicsUnityLoadApplication

UnityInitApplicationGraphics执行大量内部工作,例如设置图形设备和初始化许多 Unity 内部系统。它还通过加载资源系统中包含的所有文件的索引来初始化资源系统。

Unity 的资源系统在其数据中包含每个资源文件,这些数据位于项目文件夹的文件夹中。这包括文件夹子文件夹中的任何文件。因此,初始化 Resources 系统所需的时间与应用程序项目中文件夹中的文件数相关。ResourcesAssetsResourcesResources

UnityLoadApplication包含加载和初始化项目中的第一个场景的方法。这包括反序列化和实例化显示第一个场景所需的数据,例如编译着色器、上传纹理和实例化游戏对象。此外,Unity 还会执行第一个场景中所有 s 的回调。AwakeMonoBehaviour

这就意味着,如果在项目的第一个场景中的 回调中存在任何执行时间很长的代码,那么该代码可能会导致项目的初始启动时间的延长。 解决此问题的方法是删除这些运行速度慢的代码,或者在应用程序生命周期的其他地方执行该代码。Awake

解析运行时跟踪

对于在初始启动时间之后捕获的分析跟踪,主要关注点是方法 。这是 Unity 的主循环,其中的代码每帧运行一次。PlayerLoop

示例 Unity 项目的仪器跟踪
示例 Unity 项目的仪器跟踪

上面的屏幕截图演示了 中对性能影响最大的几种方法。注意:其中的方法名称可能因 Unity 版本而异。PlayerLoopPlayerLoop

PlayerRender是运行 Unity 渲染系统的方法。这包括剔除对象、计算动态批次以及向 GPU 提交绘制指令。任何图像效果或基于渲染的脚本回调(例如 OnWillRenderObject)也在此处运行。通常,这应该是项目交互式时 CPU 时间的最大消耗者。

BaseBehaviourManager调用 的三个模板化版本。这些调用附加到当前场景中活动游戏对象的 s 中的某些回调:CommonUpdateMonoBehaviour

  • CommonUpdate<UpdateManager> 调用 回调Update
  • CommonUpdate<LateUpdateManager> 调用 回调LateUpdate
  • CommonUpdate<FixedUpdateManager> 调用 (如果物理系统已勾选)FixedUpdate

通常,是检查最有用的方法族,因为它是在 Unity 项目中运行的大多数脚本代码的入口点。BaseBehaviourManager::CommonUpdate<UpdateManager>

还有其他几种可用于检查的方法:

  • UI::CanvasManager如果项目使用 UGUI 系统,则调用多个不同的回调。这包括 Unity UI 的批处理计算和布局更新;最常导致在探查器中出现的两个操作。CanvasManager
  • DelayedCallManager::Update运行协程。
  • PhysicsManager::FixedUpdate运行 PhysX 物理系统。这主要涉及运行 PhysX 的内部代码。当前场景中物理对象的数量,例如和影响 PhysX 的内部代码。基于物理的回调也出现在此处:特别是和 。RigidbodyColliderOnTriggerStayOnCollisionStay

如果项目使用的是 2D 物理,则在 下显示为一组类似的调用。Physics2DManager::FixedUpdate

分析脚本方法

在使用 IL2CPP 交叉编译的平台上调用脚本时,请查找包含对象的跟踪行。这是 Unity 的内部本机代码转换到脚本运行时以执行脚本代码的点。注意:从技术上讲,Unity 通过 IL2CPP 运行 C# 代码后,它也将成为本机代码。但是,此交叉编译代码主要通过 IL2CPP 运行时框架执行方法,与手写C++不同。ScriptingInvocation

来自示例 Unity 项目的跟踪
来自示例 Unity 项目的跟踪

在上面的屏幕截图中,嵌套在该行下方的方法属于 Unity 每帧执行一次的交叉编译 C# 脚本的一部分。RuntimeInvoker_Void

跟踪行的名称是原始类的名称,后跟下划线和原始方法的名称。在此跟踪示例中,您可以看到 和其他几种方法。这些是大多数 .EventSystem.UpdatePlayerShooting.UpdateUpdateUpdateMonoBehaviours

您可以展开这些方法以查看其中的哪些方法消耗了 CPU 时间。这包括项目中的其他脚本方法、Unity API 和 C# 库代码。

上面的跟踪显示,该方法是每帧对整个 UI 进行一次光线投射。此方法检测是否有任何触摸事件悬停在或激活任何 UI 元素上。循环访问所有 UI 元素并测试鼠标的位置是否在其边界矩形内的方法会占用大量资源。StandaloneInputModule.Process

资源加载

您还可以在 CPU 跟踪中识别资产加载。指示资源加载的主要方法是 。此方法将二进制数据流从文件连接到 Unity 的序列化系统,该系统通过名为 .该方法适用于所有资源类型,例如纹理、单行为和粒子系统。SerializedFile::ReadObjectTransferTransfer

场景加载跟踪
场景加载跟踪

上面的屏幕截图是 Unity 加载场景的痕迹。加载场景时,Unity 会读取并反序列化场景中的所有资源,如下面对各种方法的调用所示。TransferSerializedFile::ReadObject

如果您在运行时看到性能卡顿,并且性能跟踪显示使用了大量时间,则意味着资产加载降低了帧速率。注意:通常在 或资产包 API 请求同步资产加载时出现在主线程上。SerializedFile::ReadObjectSerializedFile::ReadObjectSceneManagerResources

要解决这种性能卡顿问题,您可以使资产加载异步(这会将繁重的调用移动到工作线程),或预加载某些繁重的资产。ReadObject

TransferUnity 克隆对象(由跟踪中的方法表示)时,也会显示调用。如果调用下方显示调用 ,则 Unity 不会从存储中加载资源。相反,Unity 会将旧对象的数据传输到新对象。为此,Unity 将序列化旧对象,并将生成的数据反序列化为新对象。CloneObjectTransferCloneObject

此文由3D建模学习工作室整理翻译,转载请注明出处!

上一篇:Unity3D:低级原生插件 Profiler API (mvrlink.com)

下一篇:Unity3D:日志文件 (mvrlink.com)

NSDT场景编辑器 | NSDT 数字孪生 | GLTF在线编辑器 | 3D模型在线转换 | UnrealSynth虚幻合成数据生成器 | 3D模型自动纹理化工具
2023 power by nsdt©鄂ICP备2023000829号