如何复用已加载的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
相关产品推荐
相关产品推荐

