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

如何复用已加载的Addressable资源,避免重复加载报错

解决方案

核心思路

  • 用字典缓存已加载的AssetReference与对应预制件的映射,彻底避免重复调用LoadAssetAsync
  • 每次实例化前先检查缓存:存在则直接用缓存的预制件实例化;不存在才执行加载逻辑,加载成功后立即存入缓存

修改后的代码

using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.ResourceManagement.AsyncOperations;

public class SquareObjectsDistributor : MonoBehaviour
{
    public SquareObject[] SquareObjectArray;
    // 缓存已加载的AssetReference对应的预制件
    private Dictionary<AssetReference, GameObject> _loadedPrefabsCache = new Dictionary<AssetReference, GameObject>();

    [System.Serializable]
    public class SquareObject {
        public string sqObject;
        public AssetReference sqObjectReference;
        public Vector3 sqObjectPosition;
        public Vector3 sqObjectRotation;
    }

    public void DistributeObjects(int whichSquare) {
        for(int i = 0; i < SquareObjectArray.Length; i++)
        {
            InstantiateSquareObjects(whichSquare, i);
        }
    }

    void InstantiateSquareObjects(int whichSquare, int whichObject) {
        var squareObj = SquareObjectArray[whichObject];
        Debug.Log("Object_" + whichSquare + "_" + whichObject);

        // 先检查缓存中是否已有该资源
        if (_loadedPrefabsCache.TryGetValue(squareObj.sqObjectReference, out GameObject cachedPrefab))
        {
            // 直接使用缓存的预制件实例化
            InstantiateFromPrefab(cachedPrefab, whichSquare, whichObject);
            return;
        }

        // 缓存中没有,执行加载逻辑
        squareObj.sqObjectReference.LoadAssetAsync<GameObject>().Completed += (asyncOperationHandle) => {
            if(asyncOperationHandle.Status == AsyncOperationStatus.Succeeded) {
                var loadedPrefab = asyncOperationHandle.Result;
                // 将加载成功的预制件存入缓存
                _loadedPrefabsCache.Add(squareObj.sqObjectReference, loadedPrefab);
                // 实例化对象
                InstantiateFromPrefab(loadedPrefab, whichSquare, whichObject);
            } else {
                Debug.Log($"Failed to load object: {squareObj.sqObject}");
            }
        };
    }

    // 提取实例化逻辑为单独方法,避免重复代码
    void InstantiateFromPrefab(GameObject prefab, int whichSquare, int whichObject)
    {
        var squareObj = SquareObjectArray[whichObject];
        GameObject newObject = Instantiate(prefab, squareObj.sqObjectPosition, Quaternion.Euler(squareObj.sqObjectRotation)) as GameObject;
        newObject.name = "Object_" + whichSquare + "_" + whichObject;
    }

    // 可选:游戏退出或不再需要资源时释放缓存(根据需求调用)
    private void OnDestroy()
    {
        foreach (var kvp in _loadedPrefabsCache)
        {
            kvp.Key.ReleaseAsset();
        }
        _loadedPrefabsCache.Clear();
    }
}

关键说明

  • _loadedPrefabsCache字典负责记录每个已加载的AssetReference对应的预制件,确保同一资源只加载一次
  • 实例化逻辑提取到InstantiateFromPrefab方法,减少代码冗余,方便后续维护
  • 可选的OnDestroy方法用于在对象销毁时释放Addressable资源,避免内存泄漏;如果游戏全程需要复用这些资源,可以去掉这个方法,在游戏结束阶段统一释放

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 05:30:50