ARCore 中文文档 下载 App

维持 FPS 帧率稳定的实战技巧

为什么 AR 应用特别容易掉帧

普通 3D 游戏可以专注于"把画面渲染出来"——60fps 就够好了。AR 应用每帧需要做:

摄像头采集(~30ms)+
ARCore SLAM + 平面检测 + 光照估算(~10ms,随帧数增加)+
深度图生成(启用 Depth API 时 +10~20ms)+
你的 3D 渲染(~16ms @ 60fps)+
遮挡渲染(额外开销)
──────────────────────────
总计:很容易超过 33ms(30fps),更别说 16ms(60fps)

ARCore 本身在不断优化,但开发者的 3D 渲染是最大的变量——同样的硬件,好的渲染管线和差的可能差 2~3 倍帧率。

帧率诊断:先搞清楚谁在拖后腿

方法一:Android Profile GPU Rendering

开发者选项 → Profile GPU Rendering 选择 "On screen bars"——屏幕上会实时显示每帧渲染时间的直方图,彩色分解 CPU/GPU/IO 各部分耗时。

方法二:Unity Profiler

Unity 的 Profiler 是最强大的性能分析工具:

方法三:ARCore Debug Overlay

ARCore 自带调试叠加层——在 Session 创建时开启:

session.configure(
    Session.Config(context).apply {
        // 在屏幕上显示 SLAM、平面检测等状态
        setShowDiagnostics(true)
    }
)

Debug Overlay 会显示:

渲染层面优化(最大收益)

优化一:减少 Draw Call

AR 场景的 Draw Call 数量直接决定 GPU 忙碌程度。主要手段:

手段说明效果
静态批处理把多个固定不动的静态物体合并渲染减少独立物体的 Draw Call
GPU Instancing同类物体一次 Draw Call 渲染多个实例适合大量重复物体(如草地、栏杆)
材质合并把多张 2K 纹理图集成为一张 4K Texture Atlas减少 Material 切换开销
减少透明物体透明物体需要额外的排序和渲染数量控制在 5 个以内
简化材质关闭不需要的 Shader Pass(如 ShadowCasterPass)每少一个 Pass 省一次 Draw Call

优化二:降低分辨率(最简单有效的 AR 优化)

AR 应用最激进的优化手段——把渲染分辨率降到物理屏幕分辨率的 75% 甚至 50%,GPU 开销直接降低到原来的 56% 或 25%。

// Android 原生:设置渲染分辨率
glSurfaceView.setEGLContextClientVersion(2)
glSurfaceView.setEGLConfigChooser(8, 8, 8, 8, 16, 0)

// Unity:URP Asset 中设置 Render Scale
// 0.75 = 75% 分辨率,UI 分辨率不受影响

75% 分辨率在大多数手机上视觉效果差别不明显(AR 摄像头画面已经占了大部分屏幕),但能显著提升帧率。

优化三:遮挡渲染的成本控制

遮挡渲染需要写深度缓冲——对低端设备来说这是额外开销。分级策略:

设备档次遮挡策略
旗舰(Pixel 5+、iPhone 12+)完整遮挡 + Depth API
中端简化遮挡(只遮挡大型平面)
低端关闭遮挡

用代码自动判断:

// 检查 GPU 性能等级
val gpuLevel = getGpuPerformanceLevel()
when (gpuLevel) {
    PERFORMANCE_HIGH -> enableFullOcclusion()
    PERFORMANCE_MEDIUM -> enableSimplifiedOcclusion()
    PERFORMANCE_LOW -> disableOcclusion()
}

ARCore 层面优化

减少 Trackable 数量

// 每一帧的 session.getAllTrackables<T>() 是 O(n) 开销
// 如果有几百个 Trackable(大量平面 + 特征点 + Augmented Image)
// 每次遍历都会花不少时间

// 优化:
// 1. 定期清理已经合并或停止跟踪的 Plane
// 2. 限制同时活跃的 Augmented Image 数据库大小
// 3. 不再需要的 Anchor 及时 detach

关闭不需要的 API

每个启用的 ARCore API 都有计算开销:

session.configure(
    Session.Config(context).apply {
        // 只开用到的 API
        setLightEstimationMode(LightEstimationMode.AMBIENT_INTENSITY)  // 只开基础光照
        // setLightEstimationMode(LightEstimationMode.ENVIRONMENTAL_HDR) // HDR 关掉更省

        // 不做 Hit Test 就关掉平面检测
        // setPlaneFindingMode(PlaneFindingMode.DISABLED)
    }
)

帧处理频率

ARCore 默认以 30fps 处理摄像头画面——不需要强行提高到 60fps:

渲染管线优化清单(按影响排序)

优先级优化项潜在 FPS 提升
1降低渲染分辨率到 75%50%+
2减少 Draw Call(批处理 / Instancing)20~40%
3简化材质 Shader(减少 Pass / 关闭 Shadow)15~25%
4减少透明物体数量10~15%
5纹理压缩 + Mipmap10%+
6遮挡渲染分级(低端关闭)10~20%
7关闭 HDR 光照估算5~10%
8清理无用 Trackable 和 Anchor3~5%