Add prototype gameplay loop with character/battlefield assets and server game APIs.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -1,39 +1,90 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using YooAsset;
|
||||
|
||||
namespace HotUpdate.UI
|
||||
{
|
||||
/// <summary>
|
||||
/// UI Prefab 加载:编辑器 AssetDatabase;运行时优先 DefaultPackage 寻址。
|
||||
/// 异步加载并持有资源句柄,随 UiManager 销毁统一释放。
|
||||
/// </summary>
|
||||
public sealed class UiPrefabLoader
|
||||
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 GameObject Load(string prefabName)
|
||||
public UiPrefabLoader(ResourcePackage preferredPackage = null, string folder = PrefabFolder)
|
||||
{
|
||||
if (string.IsNullOrEmpty(prefabName)) return null;
|
||||
_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)
|
||||
{
|
||||
// DefaultPackage 或任意已初始化包
|
||||
var packages = new[] { "DefaultPackage", "Art" };
|
||||
foreach (var name in packages)
|
||||
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 (!YooAssets.TryGetPackage(name, out var pkg)) continue;
|
||||
if (pkg.InitializeStatus != EOperationStatus.Succeeded) continue;
|
||||
var handle = pkg.LoadAssetSync<GameObject>(prefabName);
|
||||
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)
|
||||
return handle.GetAssetObject<GameObject>();
|
||||
{
|
||||
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 path = $"{PrefabFolder}/{prefabName}.prefab";
|
||||
return UnityEditor.AssetDatabase.LoadAssetAtPath<GameObject>(path);
|
||||
var editorPrefab = UnityEditor.AssetDatabase.LoadAssetAtPath<GameObject>($"{_folder}/{prefabName}.prefab");
|
||||
if (editorPrefab != null) _cache[prefabName] = editorPrefab;
|
||||
onLoaded?.Invoke(editorPrefab);
|
||||
#else
|
||||
return null;
|
||||
onLoaded?.Invoke(null);
|
||||
#endif
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (_disposed) return;
|
||||
_disposed = true;
|
||||
foreach (var handle in _handles) handle.Release();
|
||||
_handles.Clear();
|
||||
_cache.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user