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

Unity AR中Destroy延迟销毁失效问题排查求助

Unity AR延迟销毁预制体失效问题解决

问题根源

  1. 父物体连带销毁:你将预制体实例化后挂载在ARTrackedImage的Transform下,当AR系统触发removed事件时,Unity会立即销毁该ARTrackedImage对应的GameObject,其所有子物体(包括你的预制体)会被连带销毁,导致你设置的延迟销毁参数完全失效。
  2. 字典引用过早移除:调用Destroy后立刻从字典中移除预制体引用,虽不直接导致立即销毁,但会丢失实例追踪状态,后续逻辑易出问题。

修复方案

  1. 将预制体从ARTrackedImage的Transform下脱离,避免父物体销毁时被连带销毁;
  2. 使用协程控制延迟销毁顺序,确保销毁完成后再移除字典中的引用。

修改后的代码

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.XR.ARFoundation;
using UnityEngine.XR.ARSubsystems;
using System;

[RequireComponent(typeof(ARTrackedImageManager))]
public class PlaceTrackedImages : MonoBehaviour
{
    private ARTrackedImageManager _trackedImagesManager;
    public GameObject[] ArPrefabs;
    private readonly Dictionary<string, GameObject> _instantiatedPrefabs = new Dictionary<string, GameObject>();

    private void Awake()
    {
        _trackedImagesManager = GetComponent<ARTrackedImageManager>();
    }

    private void OnEnable()
    {
        _trackedImagesManager.trackedImagesChanged += OnTrackedImagesChanged;
    }

    private void OnDisable()
    {
        _trackedImagesManager.trackedImagesChanged -= OnTrackedImagesChanged;
    }

    private void OnTrackedImagesChanged(ARTrackedImagesChangedEventArgs eventArgs)
    {
        // 处理新增/更新的追踪图像
        foreach (var trackedImage in eventArgs.updated)
        {
            var imageName = trackedImage.referenceImage.name;
            foreach (var curPrefab in ArPrefabs)
            {
                if (string.Compare(curPrefab.name, imageName, StringComparison.OrdinalIgnoreCase) == 0 && !_instantiatedPrefabs.ContainsKey(imageName))
                {
                    var newPrefab = Instantiate(curPrefab, trackedImage.transform);
                    _instantiatedPrefabs[imageName] = newPrefab;
                }
            }
        }

        // 设置预制体激活状态
        foreach (var trackedImage in eventArgs.updated)
        {
            if (_instantiatedPrefabs.TryGetValue(trackedImage.referenceImage.name, out var prefab))
            {
                prefab.SetActive(trackedImage.trackingState == TrackingState.Tracking);
            }
        }

        // 处理移除的追踪图像
        foreach (var trackedImage in eventArgs.removed)
        {
            var imageName = trackedImage.referenceImage.name;
            if (_instantiatedPrefabs.TryGetValue(imageName, out var prefab))
            {
                // 将预制体从ARTrackedImage父物体下脱离
                prefab.transform.SetParent(null);
                // 启动协程延迟销毁并移除字典引用
                StartCoroutine(DelayedDestroyAndRemove(imageName, prefab, 10f));
            }
        }
    }

    private IEnumerator DelayedDestroyAndRemove(string imageName, GameObject prefab, float delay)
    {
        yield return new WaitForSeconds(delay);
        Destroy(prefab);
        _instantiatedPrefabs.Remove(imageName);
    }
}

额外优化点

  • 新增TryGetValue判断,避免字典键不存在时抛出空引用异常;
  • 协程方法明确分离延迟销毁和字典移除逻辑,保证执行顺序正确。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 22:55:58