using System; using System.Collections; using System.Collections.Generic; using UnityEngine; using YooAsset; namespace HotUpdate.UI { /// /// 异步加载并持有资源句柄,随 UiManager 销毁统一释放。 /// public sealed class UiPrefabLoader : IDisposable { public const string PrefabFolder = "Assets/Bundles/UI/Prefab"; readonly ResourcePackage _preferredPackage; readonly string _folder; readonly Dictionary _cache = new Dictionary(); readonly List _handles = new List(); bool _disposed; public UiPrefabLoader(ResourcePackage preferredPackage = null, string folder = PrefabFolder) { _preferredPackage = preferredPackage; _folder = folder; } public IEnumerator LoadAsync(string prefabName, Action onLoaded) { if (_disposed || string.IsNullOrEmpty(prefabName)) { onLoaded?.Invoke(null); yield break; } if (_cache.TryGetValue(prefabName, out var cached) && cached != null) { onLoaded?.Invoke(cached); yield break; } var packages = new List(); if (_preferredPackage != null) packages.Add(_preferredPackage); if (YooAssets.IsInitialized) { foreach (var name in new[] { "DefaultPackage", "Art" }) if (YooAssets.TryGetPackage(name, out var pkg) && !packages.Contains(pkg)) packages.Add(pkg); } foreach (var package in packages) { if (package.InitializeStatus != EOperationStatus.Succeeded) continue; foreach (var address in new[] { prefabName, $"{_folder}/{prefabName}.prefab" }) { if (!package.IsLocationValid(address)) continue; var handle = package.LoadAssetAsync(address); _handles.Add(handle); yield return handle; if (_disposed) yield break; if (handle.Status == EOperationStatus.Succeeded) { var prefab = handle.GetAssetObject(); if (prefab != null) { _cache[prefabName] = prefab; onLoaded?.Invoke(prefab); yield break; } } _handles.Remove(handle); handle.Release(); } } #if UNITY_EDITOR var editorPrefab = UnityEditor.AssetDatabase.LoadAssetAtPath($"{_folder}/{prefabName}.prefab"); if (editorPrefab != null) _cache[prefabName] = editorPrefab; onLoaded?.Invoke(editorPrefab); #else onLoaded?.Invoke(null); #endif } public void Dispose() { if (_disposed) return; _disposed = true; foreach (var handle in _handles) handle.Release(); _handles.Clear(); _cache.Clear(); } } }