91 lines
3.3 KiB
C#
91 lines
3.3 KiB
C#
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
using YooAsset;
|
|
|
|
namespace HotUpdate.UI
|
|
{
|
|
/// <summary>
|
|
/// 异步加载并持有资源句柄,随 UiManager 销毁统一释放。
|
|
/// </summary>
|
|
public sealed class UiPrefabLoader : IDisposable
|
|
{
|
|
public const string PrefabFolder = "Assets/Bundles/UI/Prefab";
|
|
readonly ResourcePackage _preferredPackage;
|
|
readonly string _folder;
|
|
readonly Dictionary<string, GameObject> _cache = new Dictionary<string, GameObject>();
|
|
readonly List<AssetHandle> _handles = new List<AssetHandle>();
|
|
bool _disposed;
|
|
|
|
public UiPrefabLoader(ResourcePackage preferredPackage = null, string folder = PrefabFolder)
|
|
{
|
|
_preferredPackage = preferredPackage;
|
|
_folder = folder;
|
|
}
|
|
|
|
public IEnumerator LoadAsync(string prefabName, Action<GameObject> 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<ResourcePackage>();
|
|
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<GameObject>(address);
|
|
_handles.Add(handle);
|
|
yield return handle;
|
|
if (_disposed) yield break;
|
|
if (handle.Status == EOperationStatus.Succeeded)
|
|
{
|
|
var prefab = handle.GetAssetObject<GameObject>();
|
|
if (prefab != null)
|
|
{
|
|
_cache[prefabName] = prefab;
|
|
onLoaded?.Invoke(prefab);
|
|
yield break;
|
|
}
|
|
}
|
|
_handles.Remove(handle);
|
|
handle.Release();
|
|
}
|
|
}
|
|
|
|
#if UNITY_EDITOR
|
|
var editorPrefab = UnityEditor.AssetDatabase.LoadAssetAtPath<GameObject>($"{_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();
|
|
}
|
|
}
|
|
}
|