using System; using System.Collections.Generic; using System.Threading.Tasks; using UnityEngine; using UnityEngine.AddressableAssets; using UnityEngine.AddressableAssets.ResourceLocators; using UnityEngine.ResourceManagement.AsyncOperations; using UnityEngine.ResourceManagement.ResourceLocations; namespace BrewMonster.Scripts { public class AddressableManager : MonoSingleton { private bool _isInitialized = false; private Dictionary> _loadedAssets = new(); public event Action OnDispose; protected override void Initialize() { base.Initialize(); _isInitialized = false; Addressables.InitializeAsync().Completed += OnInitializeComplete; } void OnInitializeComplete(AsyncOperationHandle handle) { if (handle.Status == AsyncOperationStatus.Succeeded) { _isInitialized = true; BMLogger.Log($"AddressableManager: Initialized"); } else { // print out the error BMLogger.LogError($"AddressableManager: Failed to initialize: {handle.OperationException?.Message} {handle.OperationException?.StackTrace}"); } } /// /// Load an asset asynchronously. The address should look like this: "models/npcs/npc/魅灵首领/魅灵首领/魅灵首领.prefab" /// /// public async Task LoadPrefabAsync(string assetPath) { if (_loadedAssets.ContainsKey(assetPath)) { return _loadedAssets[assetPath].Result; } try { var handle = Addressables.LoadAssetAsync(assetPath); await handle.Task; _loadedAssets[assetPath] = handle; return handle.Result; } catch (System.Exception e) { BMLogger.LogError(e.StackTrace); return null; } } /// /// When the asset is no longer needed, call this method to unload it. /// /// The asset path used when loading the asset public void ReleaseAsset(string assetPath) { if (_loadedAssets.TryGetValue(assetPath, out var handle)) { if (handle.IsValid()) { Addressables.Release(handle); } _loadedAssets.Remove(assetPath); BMLogger.Log($"AddressableManager: Released asset: {assetPath}"); } else { BMLogger.LogWarning($"AddressableManager: Asset not found in cache: {assetPath}"); } } /// /// Release a specific asset by its handle directly. /// /// The async operation handle to release public void ReleaseAsset(AsyncOperationHandle handle) { if (handle.IsValid()) { Addressables.Release(handle); } } /// /// Release all loaded assets from the cache. /// public void ReleaseAllAssets() { foreach (var kvp in _loadedAssets) { if (kvp.Value.IsValid()) { Addressables.Release(kvp.Value); } } _loadedAssets.Clear(); BMLogger.Log("AddressableManager: Released all assets"); } /// /// Check if an asset is currently loaded in the cache. /// /// The asset path to check /// True if the asset is loaded public bool IsAssetLoaded(string assetPath) { return _loadedAssets.ContainsKey(assetPath) && _loadedAssets[assetPath].IsValid(); } /// /// Get the count of currently loaded assets. /// public int LoadedAssetCount => _loadedAssets.Count; private void OnDestroy() { OnDispose?.Invoke(); ReleaseAllAssets(); } } }