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

Unity中如何正确暂停/冻结AR Camera并保留冻结帧画面?

AR 相机临时暂停(冻结帧效果)实现方案

问题原因

直接通过Time.timeScale = 0实现全局暂停会触发黑屏、崩溃,核心原因两点:

  • AR Foundation的ARCameraBackground、ARSession更新逻辑与引擎时间轴绑定,时间缩放为0时会停止相机纹理提交,但底层硬件相机仍在推送帧数据,队列堆积、纹理引用失效就会出现黑屏。
  • AROcclusionManager需要逐帧同步相机彩色帧与硬件深度数据,时间停滞时两类数据不同步,会直接触发内存访问错误导致应用崩溃。

实现步骤

不要在AR组件运行状态下直接修改全局时间缩放,按以下顺序处理即可实现冻结帧暂停效果,无黑屏、崩溃问题:

  • 暂停前先抓取当前帧作为冻结覆盖层:提前在场景中添加一个铺满全屏的RawImage,放在所有场景内容、UI的最下层(仅盖住AR渲染层),暂停触发时第一时间把当前屏幕的AR渲染结果拷贝到这个RawImage上,作为暂停时的静态显示画面。
  • 关闭所有AR相关组件:抓帧完成后,依次禁用ARSession、ARCameraBackground、AROcclusionManager组件,切断AR底层的帧更新、深度计算逻辑,从根源避免时间停滞后的数据不同步问题。
  • 再执行全局暂停逻辑:AR组件全部禁用后,再设置Time.timeScale = 0暂停自身游戏逻辑即可,此时AR相关逻辑已经停止运行,不会触发异常。
  • 恢复时按反向顺序执行:先把Time.timeScale设回1,再启用ARSession、ARCameraBackground,等待AR跟踪状态恢复正常(ARSession.state == SessionTracking)后,最后启用AROcclusionManager,隐藏冻结帧覆盖层并销毁临时纹理释放内存。

参考实现代码

using System.Collections;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.XR.ARFoundation;

public class ARPauseHandler : MonoBehaviour
{
    [Header("AR Core References")]
    [SerializeField] private ARSession _arSession;
    [SerializeField] private ARCameraBackground _arCameraBg;
    [SerializeField] private AROcclusionManager _arOcclusion;
    
    [Header("UI Reference")]
    [SerializeField] private RawImage _freezeOverlay;

    private bool _isPaused;

    public void SwitchPauseState()
    {
        _isPaused = !_isPaused;
        if (_isPaused)
        {
            // 抓取当前AR帧
            var currentFrame = new Texture2D(Screen.width, Screen.height, TextureFormat.RGB24, false);
            currentFrame.ReadPixels(new Rect(0, 0, Screen.width, Screen.height), 0, 0);
            currentFrame.Apply();
            _freezeOverlay.texture = currentFrame;
            _freezeOverlay.gameObject.SetActive(true);
            
            // 关闭所有AR组件
            _arSession.enabled = false;
            _arCameraBg.enabled = false;
            _arOcclusion.enabled = false;
            
            // 最后暂停游戏逻辑
            Time.timeScale = 0;
        }
        else
        {
            StartCoroutine(ResumeRoutine());
        }
    }

    private IEnumerator ResumeRoutine()
    {
        // 先恢复时间轴
        Time.timeScale = 1;
        
        // 启动AR Session等待跟踪恢复
        _arSession.enabled = true;
        _arCameraBg.enabled = true;
        while (ARSession.state != ARSessionState.SessionTracking)
        {
            yield return null;
        }
        
        // 跟踪恢复后再开遮挡
        _arOcclusion.enabled = true;
        
        // 隐藏冻结层释放内存
        _freezeOverlay.gameObject.SetActive(false);
        Destroy(_freezeOverlay.texture);
    }
}

避坑提示

  • 所有AR组件的启用/禁用操作必须在Time.timeScale = 1的状态下执行,不要在时间暂停状态下操作AR组件。
  • 冻结帧的RawImage记得开启preserveAspect选项,避免不同屏幕比例下画面拉伸。
  • 如果项目使用自定义渲染管线,要确认AR背景渲染Pass在抓帧逻辑前执行,避免抓到全黑/空帧。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.31 12:51:22