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,4 +1,5 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
@@ -14,28 +15,46 @@ namespace HotUpdate.UI
|
||||
readonly Dictionary<string, GameObject> _opened = new Dictionary<string, GameObject>(StringComparer.Ordinal);
|
||||
Transform _root;
|
||||
UiPrefabLoader _loader;
|
||||
readonly HashSet<string> _loading = new HashSet<string>(StringComparer.Ordinal);
|
||||
public string Theme { get; private set; } = UiThemeCatalog.Candy;
|
||||
|
||||
public void Init(Transform root, UiPrefabLoader loader)
|
||||
public void Init(Transform root, UiPrefabLoader loader, string theme = UiThemeCatalog.Candy)
|
||||
{
|
||||
Instance = this;
|
||||
_root = root;
|
||||
_loader = loader ?? new UiPrefabLoader();
|
||||
Theme = UiThemeCatalog.Normalize(theme);
|
||||
}
|
||||
|
||||
public GameObject Open(string prefabName, int siblingIndex = -1)
|
||||
public IEnumerator OpenAsync(string prefabName, Action<GameObject> onOpened, int siblingIndex = -1)
|
||||
{
|
||||
if (string.IsNullOrEmpty(prefabName)) return null;
|
||||
if (string.IsNullOrEmpty(prefabName)) { onOpened?.Invoke(null); yield break; }
|
||||
while (_loading.Contains(prefabName)) yield return null;
|
||||
if (_opened.TryGetValue(prefabName, out var existing) && existing != null)
|
||||
{
|
||||
existing.SetActive(true);
|
||||
return existing;
|
||||
onOpened?.Invoke(existing);
|
||||
yield break;
|
||||
}
|
||||
|
||||
var prefab = _loader.Load(prefabName);
|
||||
_loading.Add(prefabName);
|
||||
GameObject prefab = null;
|
||||
try
|
||||
{
|
||||
var assetName = UiThemeCatalog.Resolve(prefabName, Theme);
|
||||
yield return _loader.LoadAsync(assetName, loaded => prefab = loaded);
|
||||
if (prefab == null && assetName != prefabName)
|
||||
{
|
||||
Debug.LogWarning($"[UI] Missing {assetName}; falling back to {prefabName}. Include both themes in the resource package.");
|
||||
yield return _loader.LoadAsync(prefabName, loaded => prefab = loaded);
|
||||
}
|
||||
}
|
||||
finally { _loading.Remove(prefabName); }
|
||||
if (prefab == null)
|
||||
{
|
||||
Debug.LogError($"[UiManager] prefab not found: {prefabName}");
|
||||
return null;
|
||||
onOpened?.Invoke(null);
|
||||
yield break;
|
||||
}
|
||||
|
||||
var go = Instantiate(prefab, _root, false);
|
||||
@@ -43,13 +62,7 @@ namespace HotUpdate.UI
|
||||
if (siblingIndex >= 0)
|
||||
go.transform.SetSiblingIndex(siblingIndex);
|
||||
_opened[prefabName] = go;
|
||||
return go;
|
||||
}
|
||||
|
||||
public T Open<T>(string prefabName) where T : Component
|
||||
{
|
||||
var go = Open(prefabName);
|
||||
return go != null ? go.GetComponentInChildren<T>(true) : null;
|
||||
onOpened?.Invoke(go);
|
||||
}
|
||||
|
||||
public void Close(string prefabName, bool destroy = false)
|
||||
@@ -72,6 +85,8 @@ namespace HotUpdate.UI
|
||||
|
||||
void OnDestroy()
|
||||
{
|
||||
StopAllCoroutines();
|
||||
_loader?.Dispose();
|
||||
if (Instance == this) Instance = null;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user