目录
返回至教程第 1 部分:
面向英特尔 x86 平台的 Unity* 优化指南: 第 1 部分
在本指南中,我们将研究优化的两个主要方面:脚本和基于编辑器。您将看到许多基于其运行所在根的各个优化的具体信息。
当您正在分析您的应用并发现无需每帧调用脚本的 Update() 功能时,您可使用几大方法减少更新量:
脚本视锥剔除
使用以下 Monobehavior 回调功能剔除在焦点未对准时无需更新的摄像头视锥以外的脚本。
图 12.当采用脚本的对象离开/进入摄像头视锥时,Monobehavior 回调功能触发
协同例程
本质上,协同例程功能可暂停并恢复执行。 在删除脚本中的原始 Update() 功能并将其替换为协同例程后,您就能够利用这一功能。 然后,您可通过yield命令对想要多久执行一次协同例程进行设置。 这一片段显示了如何创建每 2 秒调用一次的定制智能更新,而非使用每帧调用一次的默认设置:
图 13.通过协同例程实现更高效的更新
如果您正在寻找一些优化内存使用的方法,那么首先检查 Unity 分析器会很有帮助。 大概了解您管理内存方式的绝佳方法是检查 Overview 窗口的“GC Alloc”部分(图 14),并单步调试帧,直到您看到有效分配。
图 14.通过连续检查多个帧,您可确定 GC 发生和调整的时间
此外,检查调用垃圾收集的频率也会有所帮助。 若要做到这一点,需隔离“CPU Usage”子分析器中的 GarbageCollector 字段(图 15):
图 15.GC 发生时 CPU Usage 中确定的点
然后在显示收集时,您可单击图表中的峰值,并寻找对 GC.Collect 的调用(图 16)。 通过这种方式,您能够了解每次收集所用的时间:
图 16.有关 GC 的统计数字
为了避免频繁分配,最好使用结构,而非类别,在堆栈上完成分配,而非堆中。 多个至堆的分配将导致出现大量内存碎片和频繁的垃圾收集。
一般来说,您应分析您的应用,以找到使用最频繁的游戏对象和组件,并确保将这些值进行高速缓存。每个您看到的获取对象场景都是一次进行高速缓存和减少不必要计算的良机。
相同的规则也适用于游戏对象实例化。 通常,实例化是应当避免的速度相对较慢的调用。如果在每个场景中反复创建并销毁同一对象类型,那么最好保存一份相关对象清单,以在对象管理器脚本中重复使用。
Unity 建议您使用一个中央游戏管理器保存所有缓存的游戏对象清单。在应用这一技巧后,您可采纳以下代码片段,通过切换状态按钮或其他控制机制比较两种方法之间是否存在性能提升,同时实时查看CPU Usage 分析器。 下面是显示使用差异的片段(图 14):
图 17.使用 STATE 切换对象
在处理 Unity 中的动态对象时,需避免一些熟知的优化和陷阱。 无论您计划自己迁移对象,还是让 Unity 控制物理对象,您都需要将Rigidbody组件添加至您的对象, 从而告知 Unity 物理系统该对象具有可迁移性。 当您想要手动迁移对象时,只需勾选isKinematic标记即可(图 18)。此外,您还需要确保并未勾选 inspector 右上角面向该对象的static 复选框(图 19)。
图 18.勾选 isKinematic,以完全控制对象迁移
图 19.未勾选 Static 属性,以免动态对象进入静态集
为了确保您在应用中恰当处理动态对象,请打开分析器、隔离CPU Profiler的physics部分、突出显示位于物理时间步长的帧(默认每秒更新 24 次),并确认您并未在 overview 窗口的对象 FixedUpdate() 调用下看到任何“Static Collider.Move(昂贵的延误成本)”条目(图 20)。 Static Collider.Move 消息的缺少表示本部分中的物理系统正常运行。
图 20.当您未正确管理动态对象时,Static Collider.Move(昂贵的延误成本)就会出现
对于在“淡出”渲染模式下使用材料的对象,或任何可变成完全透明的对象,如果其完全透明,那么必须确保将面向该对象的MeshRenderer组件设置为禁用。这些对象将始终在绘制调用中进行分派,无论 alpha 值如何。例如,开发人员有时使用全屏四边形在事件触发时绘制脉冲输入和输出的损害指标或装饰图案效果。您需要了解当对象完全透明时引擎本身并未跟踪,如果不注意的话,就会造成资源浪费。以下是在同一场景中截取的截图,唯一不同之处在于前景中半透明对象的 alpha 值。
图 21.捕获相应 GPA 帧的5 个半透明平面。 半透明对象可见,并在 2,657.5 微秒内占据 37.4% 的场景。
图 22.5 个之前提及已将其材料的 alpha 值设置为 0 的平面。相应 GPA 帧捕获显示 GPU 仍然执行了绘制命令。这些图画在 2,316.5 微秒内占据 32.1% 的场景。
为了确保您并未分派不必要的绘制调用,您始终需要尽可能地检查与您潜在透明对象相关的 alpha 值。对于基于颜色渲染的简单材料,只需按照以下代码片段使用机制。
图 23.当编辑对象透明度时,请始终检查其是否可见,如有必要节省资源,则需将其禁用。