You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何强制Unity更新/重绘整个场景?Android相机纹理延迟排查

Unity Android原生相机纹理渲染延迟问题解答

实测延迟数据

  • 直接SurfaceTexture渲染:~80ms
  • OpenGL OES转FBO后渲染:~90ms
  • Unity 60fps渲染:100-150ms(额外近60ms延迟不符合预期)

理论渲染流程

  1. CameraHAL → OES纹理 → TextureView
  2. CameraHAL → OES纹理 → 绘制到FBO(耗时<10ms)→ GLView
  3. CameraHAL → OES纹理 → 绘制到FBO(耗时<10ms)→ Unity渲染最终纹理

当前实现逻辑

Android原生插件渲染线程中,onFrameAvailable()触发时创建FBO(或双缓冲FBO),将OES纹理绘制到FBO;Unity端在Update()中创建ExternalTexture(nativeFboTextureId)并绑定到着色器。预期延迟仅来自相机线程到绘制线程切换、OES转FBO、Unity 16.67ms绘制周期。


1. Unity是否存在内部延迟?

是,Unity渲染管线存在多个可能导致额外延迟的环节:

  • 垂直同步(VSync)对齐:Unity默认会对齐设备VSync周期(60fps下为16.67ms),若原生帧到达时机错过VSync窗口,会多等待一个周期甚至更久。
  • 外部纹理缓存机制:Unity对ExternalTexture有内部缓存,不会每帧主动读取最新原生纹理数据,可能延迟1-2帧更新。
  • 线程调度开销:Unity主线程、渲染线程与原生插件渲染线程的调度存在同步成本,当帧到达时机与Unity渲染周期不匹配时,会产生等待延迟。

2. Unity是否会使用最新的外部纹理重绘?

默认情况下不一定:

  • 在Update()中创建ExternalTexture是在Unity主线程执行,而渲染线程实际采样纹理是在后续渲染阶段,可能错过刚生成的FBO帧数据。
  • Unity不会主动监听原生纹理的更新事件,若无主动通知,无法及时获取最新帧。

3. 如何在原生帧完成时强制Unity重绘?

可以通过以下方案解决:

  • 触发Unity主动渲染:原生FBO绘制完成后,通过JNI调用UnitySendMessage,通知Unity侧调用目标相机的RequestRender()方法,强制触发一次渲染,无需等待下一个Update周期。
  • 复用ExternalTexture:初始化时创建一次ExternalTexture,后续原生帧更新后,通过JNI调用ExternalTexture.UpdateExternalTexture()直接更新纹理数据,避免重复创建的开销。
  • 双缓冲FBO正确切换:使用双缓冲FBO,帧绘制完成后立即切换缓冲,将已完成的FBO纹理ID传递给Unity,确保Unity读取的是已完成的最新帧,同时避免读取正在绘制的纹理。
  • 调整VSync设置:在Unity QualitySettings中将VSync Count设为Don't Sync,关闭垂直同步(可能导致画面撕裂,需权衡);或在原生侧控制相机帧输出频率与Unity渲染周期对齐。
  • 渲染线程级更新:在Unity侧使用OnRenderObject()回调(渲染线程执行)更新外部纹理,减少主线程到渲染线程的同步延迟;或用CommandBuffer提前设置纹理采样逻辑,确保渲染时使用最新FBO数据。

内容的提问来源于stack exchange,提问作者fluke

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 11:02:41