物理
Unity 的内置物理系统 (Nvidia PhysX) 在移动设备上开销较大。下面的提示可以帮助您每秒减少更多帧。
优化设置
在 PlayerSettings 中,尽可能选中 Prebake Collision Meshes。
启用 Prebake Collision Meshes
请务必同时编辑 Physics 设置 (Project Settings > Physics)。尽可能简化 Layer Collision Matrix。
禁用 Auto Sync Transforms 并启用 Reuse Collision Callbacks。
修改物理项目设置以进一步提高性能
留意 Profiler 的 Physics 模块是否有性能问题
简化碰撞体
网格碰撞体开销较大。用简单的原始碰撞体或网格碰撞体代替更复杂的网格碰撞体来近似原始形状。
使用原始或简化网格来表示碰撞体
使用物理方法移动刚体
使用类方法(如 MovePosition 或 AddForce)来移动 Rigidbody 对象。直接转换其 Transform 组件可能导致重新计算物理世界,在复杂场景中,这样需要较大开销。
在 FixedUpdate 中而不是 Update 中移动物理体。
修改固定时间间隔
Project Settings 中的默认 Fixed Timestep 是 0.02 (50 Hz)。根据目标帧率对此进行更改(例如,对 30 fps 设置为 0.03)。
否则,如果帧率在运行时下降,也就是说 Unity 每帧都多次调用 FixedUpdate,可能会因物理内容过多而造成 CPU 性能问题。
Maximum Allowed Timestep 对帧率下降时物理计算和 FixedUpdate 事件可以使用的时间进行限制。降低该值意味着在性能顿挫过程中,物理系统和动画会缓慢下来,但也会减小其对帧率的影响。
将以减 Fixed Timestep 修改为与目标帧率相符,降低 Maximum Allowed Timestep 以减少性能毛刺
通过 Physics Debugger 实现可视化
使用 Physics Debug 窗口 (Window > Analysis > Physics Debugger) 可帮助故障检查有问题的碰撞体或者出现差异的情况。下面是一个颜色编码的指示器,指示哪些游戏对象可以相互碰撞。
Physics Debugger 可帮助您可视化物理对象能够相互交互的方式
有关更多信息,请参阅 Unity 文档中的物理调试可视化。https://docs.unity3d.com/cn/current/Manual/PhysicsDebugVisualization.html
用户界面 UI
Unity UI (UGUI) 常常是性能问题的来源。Canvas 组件生成和更新 UI 组件的网格并向 GPU 发出绘制调用。它的运行开销很大,因此,在使用 UGUI 时,请注意以下因素。
Unity UI 文档:https://docs.unity3d.com/Packages/[email protected]/manual/index.html
划分画布
如果是包含成千上万个元素的大型画布,更新单个 UI 元素就必须更新整个画布,这可能会造成 CPU 尖峰。
利用 UGUI 的功能可以支持多个画布。根据 UI 元素的更新频率要求,划分这些元素。将静态 UI 元素保留在单独的画布上,将同时更新的动态元素保留在较小的子画布上。
确保每个画布中的 UI 元素都有相同的 Z 值、材质和纹理。
隐藏不可见的 UI 元素
可能有些 UI 元素(如仅当角色收到伤害时才出现的生命值血条)只偶尔在游戏中出现。如果不可见的 UI 元素是活动的,它仍然可能使用绘制调用。显式禁用所有不可见的 UI 组件,在需要时再重新启用。
如果只需要关闭画布的可见性,请禁用 Canvas 组件而不是游戏对象。这样就不必重新构建网格和顶点。
限制 GraphicRaycaster 和禁用 Raycast Target
输入事件(如屏上触摸或单击)需要 GraphicRaycaster 组件。它只是循环处理屏幕上的每个输入点,检查它是否在 UI 的 RectTransform 之内。
从层级视图的顶层画布中移除默认的 GraphicRaycaster。只向需要交互的各元素(按钮、滚动矩形等)添加 GraphicRaycaster。
禁用在默认情况下处于活动状态的 Ignore Reversed Graphics
另外,在所有不需要 Raycast Target 的 UI 文本和图像上将其禁用。如果是包含很多元素的复杂 UI,所有这些小更改都可以减少不必要的计算。
尽可能禁用 Raycast Target
避免使用布局组
布局组的更新很低效,应少量使用。如果内容是动态的,应完全避免不用,而是使用锚点进行比例布局。或者,创建自定义代码,在 Layout Group 组件设置 UI 之后,将该组件禁用。
Layout Group 文档:https://docs.unity3d.com/Packages/[email protected]/manual/UIAutoLayout.html
如果动态元素确实需要使用布局组(水平、垂直、网格),应避免嵌套它们,从而改善性能。
布局组会降低性能,尤其是在嵌套时
避免使用大型列表和网格视图
大型列表和网格视图开销很大。如果需要创建大型列表或网格视图(如包含成百上千项目的物品栏屏幕),可以考虑重复使用较小的 UI 元素池,而不是为每个项目都创建 UI 元素。请参阅此示例 GitHub 项目了解实际方法。
GitHub 项目:
https://github.com/boonyifei/ScrollList
避免大量使用重叠元素
对大量 UI 元素(如卡牌游戏中堆叠的卡牌)分层会造成过度绘制。自定义代码在运行时将分层元素合并到更少的元素和批次中。
使用多种分辨率和宽高比
现在,移动设备使用的分辨率和屏幕大小极为不同,创建不同的 UI 版本可以按设备提供最佳体验。
UI 版本:https://docs.unity3d.com/Packages/[email protected]/manual/HOWTO-UIMultiResolution.html
使用设备模拟器可以预览 UI 在各种受支持的设备上的呈现。您也可以在XCode 和 Android Studio 中创建虚拟设备。
设备模拟器:https://docs.unity3d.com/Manual/com.unity.device-simulator.html
使用设备模拟器预览各种屏幕格式
使用全屏 UI 时,隐藏其他全部内容
如果暂停屏幕或者启动屏幕遮住场景中的其他全部内容,则禁用摄像机对 3D 场景的渲染。同样,禁用隐藏在顶层画布之后的所有背景画布元素。
由于不需要以 60 fps 的帧率进行更新,可以考虑在全屏 UI 过程中降低 Application.targetFrameRate。
将摄像机分配给世界空间画布和摄像机空间画布
将 Event 或 Render Camera 字段留空会使 Unity 填充 Camera.main,这会导致不必要的开销。
尽可能使画布 RenderMode 采用 Screen Space - Overlay,这样就不需要摄像机。
使用世界空间 (World Space) 渲染模式时,请务必填充 Event Camera
音频
尽管音频通常不会造成性能瓶颈,还是可以进行优化以节省内存。
尽量使用单声道声音剪辑
如果要使用 3D 空间音频, 请以单声道 (single channel) 的形式创作声音剪辑,或者启用 Force To Mono 设置。在运行时定位使用的多声道声音会扁平化为单声道源,因此会增加 CPU 开销和浪费内存。
尽可能使用原始未压缩 WAV 文件作为源资源
如果使用任何压缩格式(如 MP3 或 Vorbis),Unity 会将其解压并在构建时重新压缩。这样会导致两个有损通道,从而降低最终质量。
压缩剪辑并降低压缩比特率
通过压缩减小剪辑的大小和内存使用量 :
对大多数声音使用 Vorbis(或者对不循环的声音使用 MP3)。
对常用的短声音使用 ADPCM(如脚步声、枪声)。相比于未压缩的 PCM,这样可以减小文件大小,在播放时又可以很快解码。
移动设备上的音效最高为 22,050 Hz。使用较低设置通常对最终质量影响很小,当然,请使用您自己的耳朵来判断。
优化 AudioClip 的导入设置
选择正确的加载类型
每个剪辑大小的设置都不同。
小剪辑 (< 200 kb) 应采用 Decompress on Load。将声音解压缩为原始 16 位 PCM 音频数据,会导致 CPU 开销和内存占用,因此,这仅适用于短声音。
中等剪辑 (>= 200 kb) 应保持为 Compressed in Memory。
大文件(背景音乐)应设置为 Streaming。否则,整个资源会一次性加载到内存中。
从内存中卸载静音的音频源 (AudioSources)
实现静音按钮时,不要只是将音量设置为 0。可以销毁 AudioSource 组件,从而将其从内存中卸载,这样,播放器不需要过于频繁地切换开关。
版权归原作者 爱编程的鱼 所有, 如有侵权,请联系我们删除。