Android 开发
本版块提供指南以帮助提升您的 Unity Android 应用表现。
良好表现对于所有 VR 应用都至关重要,但独立开发固有的局限性需要特别考虑。
相关资源:
本版块描述了 Android 项目的推荐目标和设置。
从开始就要对表现保持谨慎态度。
- 保持绘制调用次数处于低位。
- 注意纹理的使用和带宽。
- 将几何复杂度降至最低。
- 注意填充率。
Unity 提供了多个内置功能来帮助减少绘制调用,如批处理和剔除。
Unity 尝试在运行时合并对象,并用一次绘制调用就将它们绘制出来。这有助于减少 CPU 的开销。有两种类型的绘制调用批处理:静态批处理和动态批处理。
静态批处理用于不会移动、旋转或缩放的对象,并且必须为每个对象显式设置。要将对象标记为静态,请在对象检查器中选中静态复选框。

动态批处理用于移动的对象,并且当对象满足某些特定条件时会自动应用,如共享相同的材质、不使用实时阴影或不使用多通道着色器。请参阅 Unity 的
网格批处理介绍,了解更多关于动态批处理标准的信息。
Unity 还集成了遮挡剔除系统。对于早期 VR 游戏的建议是,优先采用规模适中的“场景”,而非“开放世界”,并且对于规模适中的场景而言,遮挡剔除可能过于复杂。有关遮挡剔除系统的更多信息,请访问 Unity 的
遮挡剔除文档页面。
- 纹理压缩:纹理压缩能显著提升表现。推荐使用 ASTC 压缩纹理格式。
- 多级渐远纹理:始终为游戏中的纹理使用多级渐远纹理。幸运的是,Unity 会在导入纹理时自动为其生成多级渐远纹理。要在纹理检查器中查看可用的多级渐远纹理选项,请将纹理类型切换为高级。
- 纹理过滤:对于 VR 来说,三线性过滤通常是一个不错的选择。它确实会带来一定的性能开销,但这是值得的。也可以使用各向异性过滤,但请确保每个片段只进行一次各向异性纹理查找。
- 纹理尺寸:优先考虑纹理细节而非几何细节,例如,使用高分辨率纹理而非更多的三角形。我们拥有大量的纹理内存,并且从表现角度来看,这几乎是免费的。也就是说,素材商店中的纹理通常分辨率过高,对于独立应用来说往往会造成浪费。这些纹理通常可以缩小尺寸,而且并不会造成明显的差异。
- 帧缓冲格式:大多数场景都应构建为与 16 位深度缓冲分辨率兼容。此外,如果您的世界主要使用预先光照的压缩纹理,则可以使用 16 位颜色缓冲区。
- 屏幕分辨率:将屏幕分辨率设置较低可能会为大多数 Unity 应用带来显著的速度提升。
将几何复杂度降至最低。每眼每帧 50,000 个静态三角形是一个保守目标。
验证模型顶点计数是否可独立运行。通常情况下,素材商店中的素材保真度较高,需要针对独立运行进行调整。
Unity 提供了一个内置的
细节层次系统,使得在一定距离观看物体时显示较低分辨率的网格。有关如何为模型设置 LODGroup 的更多信息,请参阅 Unity 的
细节层次介绍。
验证您的顶点着色器是否可独立运行。并且,在使用内置着色器时,优先选择 Mobile 版本或 Unlit 版本的着色器。
在构建场景时,要注意游戏对象数量。场景中的游戏对象和渲染器越多,消耗的内存就越多,Unity 剔除和渲染场景所需的时间也就越长。
像素复杂度:尽可能将细节烘焙到纹理中,以减少逐像素计算。例如,将镜面高光烘焙到纹理中,以避免在片段着色器中计算高光。
验证您的片段着色器是否可独立运行。并且,在使用内置着色器时,优先选择 Mobile 版本或 Unlit 版本的着色器。
过度绘制:Unity 中的不透明队列对象会按照从前到后的顺序进行渲染,并使用深度测试来最大程度地减少过度绘制。然而,透明队列中的对象则是按照从后到前的顺序进行渲染,且不进行深度测试,因此容易发生过度绘制。
应避免重叠的半透明几何体(例如,密集的粒子特效)和全屏后期处理特效。
VR 头戴设备的功能受到设备处理能力和散热能力的限制。您可以使用固定时钟级别 API 和动态时钟调节来管理头戴设备的热量和功耗。在移动 SDK 指南的
电源管理页面上,提供了有关这两个功能的详细概述。
要在 Unity 应用中设置时钟级别,请设置 OVRManager.cpuLevel ( ) 和 OVRManager.gpuLevel ( ).
本版块描述了 Android 项目最佳实践。
- 要便于进行批处理。尽可能共享材质并使用纹理图集。
- 优先选择已进行光照贴图的静态几何体。
- 对于角色和移动对象,优先选择光探针而不是动态照明。
- 始终使用烘焙的光照贴图,而不是预计算 GI。
- 使用非方向性光照贴图。
- 尽可能多地将细节烘焙到纹理中。例如,镜面反射、环境光遮蔽。
- 每只眼睛只渲染一个视图。不要使用阴影缓冲区、反射、多摄像机设置等。
- 将渲染通道的数量保持在最低水平。不要使用动态光照、后期特效,不要解析缓冲区,不要在着色器中使用抓取通道等。
- 避免使用 Alpha 测试/像素丢弃透明度。Alpha 测试会带来很高的性能开销。如果可能,请替换为 alpha 混合。
- 将 alpha 混合透明度保持在最低水平。
- 务必使用纹理压缩。我们建议使用 ASTC 纹理压缩作为全局设置。
- 在播放器设置的分辨率和呈现面板中,选中禁用深度和模板复选框。
- 请确保初始化 GPU 节流,并避免使用危险值(-1 或 > 3)。有关更多信息,请参阅我们的移动 SDK 开发人员指南中的电源管理部分。
- 避免使用全屏图像特效。
- 使用带有清除操作的多摄像机时要小心,这样做可能会导致填充成本过高。
- 避免使用 LoadLevelAsync 或 LoadLevelAdditiveAsync。这会对帧率产生巨大影响,通常最好转为黑屏并同步加载。
- 避免使用标准着色器或标准镜面反射着色器。
- 避免使用投射器,或者谨慎使用——它们可能非常消耗资源。
- 避免使用 Unity 的默认天空盒,因为它在独立版本中计算量很大。我们建议在窗口 > 照明中将天空盒设置为无(材质),并将环境光源设置为颜色。您可能还希望将 Camera.clearFlags 设置为 SolidColor(而非 Skybox)。
- 要注意场景中使用的游戏对象和组件的总数。
- 高效地为您的游戏数据和对象建模。通常情况下,内存是充足的。
- 尽量减少在 Update() 或 FixedUpdate() 中实际执行计算的对象数量。
- 在不需要时减少或消除物理模拟。
- 使用对象池来重生频繁使用的效果或对象,而不是在运行时分配新的对象。
- 使用对象池中的 AudioSources 而不是 PlayOneShot 声音,因为后者会在声音播放完毕时分配一个游戏对象并将其销毁。
- 尽可能避免昂贵的数学运算。
- 对频繁使用的组件和变换进行缓存,以避免每帧都要进行查找。
- 使用 Unity 性能分析器来:
- 识别昂贵的代码并根据需要进行优化。
- 识别和消除每帧发生的垃圾收集分配。
- 识别和消除正常游戏过程中的任何性能峰值。
- 不要使用 Unity 的 OnGUI() 调用。
- 不要启用陀螺或加速度计。在 Unity 的当前版本中,这些功能会触发昂贵的显示调用。
- 所有针对独立应用和游戏开发的最佳实践通常都适用。
本版块描述了针对独立应用的启动顺序建议和强制行为要求。
为了获得良好的 VR 体验,所有图形都应该以用户始终能看到正确的三维立体图像的方式进行渲染。此外,必须始终保持头部追踪。我们建议使用立方体贴图覆盖层作为您的启动画面(请参阅
VR 构图层),即使应用无法更新场景,它也能以稳定的帧率进行渲染。
在应用启动期间如何执行此操作,请参阅 SDKExamples 中的 Startup_Sample 场景:
- 显示纯黑色启动画面的时间要尽可能短。
- 立即加载一个包含 3D 徽标和 3D 旋转部件或进度条的小型测试场景。
- 在小型启动场景处于活动状态时,主场景在后台加载。
- 主场景完全加载后,启动场景使用淡出效果过渡到主场景。
请参阅我们
Unity 脚本参考中的 OVRPlatformMenu 类描述,以了解有关相关公共成员的详细信息。
音量按钮是预留按钮,Samsung 设备上的音量调节会自动处理。自移动 SDK 1.0.3 版本起,VrApi 也会自动处理音量控制对话框,该功能在 Unity 版本的 Utilities 1.5.0 及更高版本中也是支持的。请勿自行部署音量显示处理,否则用户将看到两个并置的显示。
通过将 VRAPI_FRAME_FLAG_INHIBIT_VOLUME_LAYER 设置为 ovrFrameParm 标志,可以覆盖自动音量显示处理。