1397 lines
50 KiB
C#
1397 lines
50 KiB
C#
using UnityEngine;
|
||
using UnityGameFramework.Runtime;
|
||
using System.Collections.Generic;
|
||
using System.Linq;
|
||
using ArtResource;
|
||
using GameFramework.Resource;
|
||
using Spine.Unity;
|
||
using System;
|
||
|
||
namespace CrazyMaple
|
||
{
|
||
/// <summary>
|
||
/// 美术资源运行时管理器(单例MonoBehaviour)- 优化版
|
||
/// 三级缓存:SO缓存 -> Sprite缓存 -> Spine缓存
|
||
///
|
||
/// 改进点:
|
||
/// 1. 增加初始化完成回调,支持外部等待
|
||
/// 2. 正确实现AssetBundle资源加载(运行时)
|
||
/// 3. 优化初始化时序,避免竞态条件
|
||
/// 4. 支持预加载配置(从manifest读取)
|
||
/// </summary>
|
||
public class ArtResourceManager : MonoBehaviour
|
||
{
|
||
private static ArtResourceManager instance;
|
||
public static ArtResourceManager Instance
|
||
{
|
||
get
|
||
{
|
||
if (instance == null)
|
||
{
|
||
GameObject go = new GameObject("ArtResourceManager");
|
||
instance = go.AddComponent<ArtResourceManager>();
|
||
DontDestroyOnLoad(go);
|
||
}
|
||
return instance;
|
||
}
|
||
}
|
||
|
||
#region 缓存结构
|
||
|
||
/// <summary>
|
||
/// 常量:SO文件夹路径
|
||
/// </summary>
|
||
private const string SO_ROOT_PATH = "Assets/Art_SubModule/Art_SO";
|
||
|
||
/// <summary>
|
||
/// SO文件缓存(启动时一次性加载所有SO,速度快~几十毫秒)
|
||
/// Key: TableId
|
||
/// </summary>
|
||
private Dictionary<int, ArtTableSO> allTables = new Dictionary<int, ArtTableSO>();
|
||
|
||
/// <summary>
|
||
/// SO名称索引(支持按Name查询)
|
||
/// Key: TableName
|
||
/// </summary>
|
||
private Dictionary<string, ArtTableSO> tablesByName = new Dictionary<string, ArtTableSO>();
|
||
|
||
/// <summary>
|
||
/// Sprite资源缓存(重量级,按需加载)
|
||
/// Key: "tableId_itemId"
|
||
/// </summary>
|
||
private Dictionary<string, Sprite> loadedSprites = new Dictionary<string, Sprite>();
|
||
|
||
/// <summary>
|
||
/// Spine资源缓存(重量级,按需加载)
|
||
/// Key: "tableId_itemId"
|
||
/// </summary>
|
||
private Dictionary<string, SkeletonDataAsset> loadedSpines = new Dictionary<string, SkeletonDataAsset>();
|
||
|
||
/// <summary>
|
||
/// 正在加载的表资源(防止重复加载)
|
||
/// Key: TableId, Value: 回调列表
|
||
/// </summary>
|
||
private Dictionary<int, List<Action<bool>>> loadingTables = new Dictionary<int, List<Action<bool>>>();
|
||
|
||
/// <summary>
|
||
/// 正在加载的Sprite(防止重复加载)
|
||
/// Key: "tableId_itemId", Value: 回调列表
|
||
/// </summary>
|
||
private Dictionary<string, List<Action<Sprite>>> loadingSprites = new Dictionary<string, List<Action<Sprite>>>();
|
||
|
||
/// <summary>
|
||
/// 正在加载的Spine(防止重复加载)
|
||
/// Key: "tableId_itemId", Value: 回调列表
|
||
/// </summary>
|
||
private Dictionary<string, List<Action<SkeletonDataAsset>>> loadingSpines = new Dictionary<string, List<Action<SkeletonDataAsset>>>();
|
||
|
||
/// <summary>
|
||
/// SO是否已初始化完成
|
||
/// </summary>
|
||
private bool isInitialized = false;
|
||
|
||
/// <summary>
|
||
/// 初始化完成时的回调列表
|
||
/// </summary>
|
||
private List<Action<bool>> initializeCallbacks = new List<Action<bool>>();
|
||
|
||
/// <summary>
|
||
/// Manifest数据(包含预加载配置)
|
||
/// </summary>
|
||
private ArtTableManifest manifest;
|
||
|
||
#endregion
|
||
|
||
private void Awake()
|
||
{
|
||
if (instance != null && instance != this)
|
||
{
|
||
Destroy(gameObject);
|
||
return;
|
||
}
|
||
|
||
instance = this;
|
||
DontDestroyOnLoad(gameObject);
|
||
|
||
// 不在Awake中自动初始化,等待外部调用
|
||
// 这样可以让ProcedurePreload控制初始化时机
|
||
}
|
||
|
||
#region 初始化
|
||
|
||
/// <summary>
|
||
/// 初始化:加载所有ArtTableSO(异步回调方式)
|
||
/// 建议在ProcedurePreload中调用,并等待回调完成
|
||
/// </summary>
|
||
/// <param name="onComplete">初始化完成回调(true=成功,false=失败)</param>
|
||
public void Initialize(Action<bool> onComplete = null)
|
||
{
|
||
if (isInitialized)
|
||
{
|
||
Debug.LogWarning("[ArtResourceManager] 已初始化,直接执行回调");
|
||
onComplete?.Invoke(true);
|
||
return;
|
||
}
|
||
|
||
// 加入回调队列
|
||
if (onComplete != null)
|
||
{
|
||
initializeCallbacks.Add(onComplete);
|
||
}
|
||
|
||
// 如果已经在加载中,直接返回
|
||
if (initializeCallbacks.Count > 1)
|
||
{
|
||
Debug.Log("[ArtResourceManager] 正在初始化中,已加入回调队列");
|
||
return;
|
||
}
|
||
|
||
var startTime = Time.realtimeSinceStartup;
|
||
Debug.Log("[ArtResourceManager] 开始加载所有ArtTableSO...");
|
||
|
||
// Editor和Runtime统一使用GameEntry.Resource.LoadAsset
|
||
LoadAllTables(success =>
|
||
{
|
||
var duration = (Time.realtimeSinceStartup - startTime) * 1000f;
|
||
|
||
if (success)
|
||
{
|
||
isInitialized = true;
|
||
Debug.Log($"[ArtResourceManager] SO初始化完成: {allTables.Count} 个表,耗时 {duration:F2}ms");
|
||
|
||
// 自动预加载配置的表
|
||
AutoPreloadTables();
|
||
}
|
||
else
|
||
{
|
||
Debug.LogError("[ArtResourceManager] SO初始化失败");
|
||
}
|
||
|
||
// 通知所有等待的回调
|
||
var callbacks = new List<Action<bool>>(initializeCallbacks);
|
||
initializeCallbacks.Clear();
|
||
foreach (var callback in callbacks)
|
||
{
|
||
callback?.Invoke(success);
|
||
}
|
||
});
|
||
}
|
||
|
||
/// <summary>
|
||
/// 加载所有SO文件(只加载SO本身,不加载引用的资源)
|
||
/// 需要先加载索引文件 art_table_manifest.json,获取所有SO的AssetName列表
|
||
/// </summary>
|
||
private void LoadAllTables(Action<bool> onComplete)
|
||
{
|
||
const string manifestPath = "Assets/Art_SubModule/Art_SO/art_table_manifest.json";
|
||
|
||
// 创建加载回调
|
||
var loadCallbacks = new LoadAssetCallbacks(
|
||
// 成功回调
|
||
(assetName, asset, duration, userData) =>
|
||
{
|
||
var manifestAsset = asset as TextAsset;
|
||
if (manifestAsset == null)
|
||
{
|
||
Debug.LogError($"[ArtResourceManager] 索引文件格式错误: {manifestPath}");
|
||
onComplete?.Invoke(false);
|
||
return;
|
||
}
|
||
|
||
// 解析JSON获取所有SO路径
|
||
manifest = JsonUtility.FromJson<ArtTableManifest>(manifestAsset.text);
|
||
|
||
if (manifest == null || manifest.tablePaths == null || manifest.tablePaths.Length == 0)
|
||
{
|
||
Debug.LogError("[ArtResourceManager] 索引文件为空,没有找到任何SO");
|
||
onComplete?.Invoke(false);
|
||
return;
|
||
}
|
||
|
||
// 遍历加载所有SO
|
||
int totalCount = manifest.tablePaths.Length;
|
||
int loadedCount = 0;
|
||
int failedCount = 0;
|
||
var soLoadStartTime = Time.realtimeSinceStartup;
|
||
var soLoadTimes = new List<(string path, float ms)>();
|
||
|
||
Debug.Log($"[ArtResourceManager] 开始加载 {totalCount} 个SO文件...");
|
||
|
||
foreach (var assetPath in manifest.tablePaths)
|
||
{
|
||
LoadSingleTable(assetPath, (success, loadTime) =>
|
||
{
|
||
if (success)
|
||
{
|
||
loadedCount++;
|
||
soLoadTimes.Add((assetPath, loadTime));
|
||
}
|
||
else
|
||
failedCount++;
|
||
|
||
// 检查是否全部加载完成
|
||
if (loadedCount + failedCount >= totalCount)
|
||
{
|
||
var totalDuration = (Time.realtimeSinceStartup - soLoadStartTime) * 1000f;
|
||
bool allSuccess = failedCount == 0;
|
||
|
||
Debug.Log($"[ArtResourceManager] SO加载完成: 成功={loadedCount}, 失败={failedCount}, 总计={totalCount}, 总耗时={totalDuration:F2}ms");
|
||
|
||
// 显示最慢的前5个SO
|
||
if (soLoadTimes.Count > 0)
|
||
{
|
||
var slowest = soLoadTimes.OrderByDescending(x => x.ms).Take(5).ToList();
|
||
Debug.Log($"[ArtResourceManager] 最慢的{slowest.Count}个SO:");
|
||
foreach (var item in slowest)
|
||
{
|
||
Debug.Log($" - {item.path}: {item.ms:F2}ms");
|
||
}
|
||
}
|
||
|
||
onComplete?.Invoke(allSuccess);
|
||
}
|
||
});
|
||
}
|
||
},
|
||
// 失败回调
|
||
(assetName, status, errorMessage, userData) =>
|
||
{
|
||
Debug.LogError($"[ArtResourceManager] 加载索引文件失败: {manifestPath}, {errorMessage}");
|
||
Debug.LogError("[ArtResourceManager] 请在Editor下运行工具生成art_table_manifest.json");
|
||
onComplete?.Invoke(false);
|
||
}
|
||
);
|
||
|
||
// 使用GameEntry.Resource.LoadAsset加载索引文件
|
||
GameEntry.Resource.LoadAsset(manifestPath, typeof(TextAsset), loadCallbacks);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 加载单个SO文件
|
||
/// </summary>
|
||
private void LoadSingleTable(string assetPath, Action<bool, float> onComplete)
|
||
{
|
||
var startTime = Time.realtimeSinceStartup;
|
||
var loadCallbacks = new LoadAssetCallbacks(
|
||
// 成功回调
|
||
(assetName, asset, duration, userData) =>
|
||
{
|
||
var loadTime = (Time.realtimeSinceStartup - startTime) * 1000f;
|
||
var table = asset as ArtTableSO;
|
||
if (table != null)
|
||
{
|
||
RegisterTable(table, assetPath);
|
||
onComplete?.Invoke(true, loadTime);
|
||
}
|
||
else
|
||
{
|
||
Debug.LogError($"[ArtResourceManager] 加载SO失败: {assetPath}");
|
||
onComplete?.Invoke(false, loadTime);
|
||
}
|
||
},
|
||
// 失败回调
|
||
(assetName, status, errorMessage, userData) =>
|
||
{
|
||
var loadTime = (Time.realtimeSinceStartup - startTime) * 1000f;
|
||
Debug.LogError($"[ArtResourceManager] 加载SO异常 [{assetPath}]: {errorMessage}");
|
||
onComplete?.Invoke(false, loadTime);
|
||
}
|
||
);
|
||
|
||
// 使用GameEntry.Resource.LoadAsset加载SO
|
||
GameEntry.Resource.LoadAsset(assetPath, typeof(ArtTableSO), loadCallbacks);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 注册SO到缓存
|
||
/// 注意:路径已经在ArtItemData中存储,无需额外缓存
|
||
/// </summary>
|
||
private void RegisterTable(ArtTableSO table, string tablePath)
|
||
{
|
||
if (allTables.ContainsKey(table.TableId))
|
||
{
|
||
Debug.LogWarning($"[ArtResourceManager] 表ID重复: {table.TableId} ({table.TableName})");
|
||
return;
|
||
}
|
||
|
||
allTables[table.TableId] = table;
|
||
|
||
if (!string.IsNullOrEmpty(table.TableName))
|
||
{
|
||
if (tablesByName.ContainsKey(table.TableName))
|
||
{
|
||
Debug.LogWarning($"[ArtResourceManager] 表名称重复: {table.TableName}");
|
||
}
|
||
else
|
||
{
|
||
tablesByName[table.TableName] = table;
|
||
}
|
||
}
|
||
|
||
Debug.Log($"[ArtResourceManager] 注册表: {table.TableId} - {table.TableName} ({table.Items.Count} 项)");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 自动预加载manifest中配置的表
|
||
/// </summary>
|
||
private void AutoPreloadTables()
|
||
{
|
||
if (manifest == null || manifest.preloadTableIds == null || manifest.preloadTableIds.Length == 0)
|
||
{
|
||
Debug.Log("[ArtResourceManager] 没有配置自动预加载的表");
|
||
return;
|
||
}
|
||
|
||
Debug.Log($"[ArtResourceManager] 开始自动预加载 {manifest.preloadTableIds.Length} 个表...");
|
||
|
||
foreach (var tableId in manifest.preloadTableIds)
|
||
{
|
||
LoadTable(tableId, success =>
|
||
{
|
||
if (success)
|
||
{
|
||
Debug.Log($"[ArtResourceManager] 自动预加载表 {tableId} 成功");
|
||
}
|
||
else
|
||
{
|
||
Debug.LogWarning($"[ArtResourceManager] 自动预加载表 {tableId} 失败");
|
||
}
|
||
});
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 索引文件的数据结构(包含预加载配置)
|
||
/// </summary>
|
||
[Serializable]
|
||
private class ArtTableManifest
|
||
{
|
||
public string[] tablePaths;
|
||
public int[] preloadTableIds;
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region 表级资源加载
|
||
|
||
/// <summary>
|
||
/// 异步加载资源表的所有引用资源(Sprite + Spine)
|
||
/// 适用场景:预加载关键表、界面预加载
|
||
/// </summary>
|
||
/// <param name="tableId">表ID</param>
|
||
/// <param name="onComplete">加载完成回调(true=成功,false=失败)</param>
|
||
public void LoadTable(int tableId, Action<bool> onComplete = null)
|
||
{
|
||
if (!isInitialized)
|
||
{
|
||
Debug.LogError("[ArtResourceManager] 未初始化,请先调用Initialize()并等待回调完成");
|
||
onComplete?.Invoke(false);
|
||
return;
|
||
}
|
||
|
||
// 检查表是否存在
|
||
if (!allTables.TryGetValue(tableId, out ArtTableSO table))
|
||
{
|
||
Debug.LogError($"[ArtResourceManager] LoadTable失败: 找不到表ID {tableId}");
|
||
onComplete?.Invoke(false);
|
||
return;
|
||
}
|
||
|
||
// 检查是否正在加载
|
||
if (loadingTables.ContainsKey(tableId))
|
||
{
|
||
Debug.Log($"[ArtResourceManager] 资源表 {tableId} 正在加载中,加入回调队列");
|
||
loadingTables[tableId].Add(onComplete);
|
||
return;
|
||
}
|
||
|
||
// 开始加载
|
||
loadingTables[tableId] = new List<Action<bool>> { onComplete };
|
||
Debug.Log($"[ArtResourceManager] 开始预加载资源表 {tableId} ({table.TableName}) 的所有资源(共 {table.Items.Count} 项)");
|
||
|
||
int totalCount = 0;
|
||
int loadedCount = 0;
|
||
int failedCount = 0;
|
||
|
||
// 统计需要加载的资源数量
|
||
foreach (var item in table.Items)
|
||
{
|
||
// 检查Sprite是否需要加载(有引用或有路径)
|
||
if (item.Sprite != null || !string.IsNullOrEmpty(item.SpritePath))
|
||
{
|
||
totalCount++;
|
||
}
|
||
|
||
// 检查Spine是否需要加载(有引用或有路径)
|
||
if (item.SpineAsset != null || !string.IsNullOrEmpty(item.SpineAssetPath))
|
||
{
|
||
totalCount++;
|
||
}
|
||
}
|
||
|
||
if (totalCount == 0)
|
||
{
|
||
Debug.LogWarning($"[ArtResourceManager] 资源表 {tableId} 没有任何Sprite或Spine资源");
|
||
NotifyLoadTableComplete(tableId, true);
|
||
return;
|
||
}
|
||
|
||
// 加载所有资源
|
||
foreach (var item in table.Items)
|
||
{
|
||
// 加载Sprite
|
||
if (item.Sprite != null || !string.IsNullOrEmpty(item.SpritePath))
|
||
{
|
||
PreloadSprite(tableId, item.Id, item, success =>
|
||
{
|
||
if (success) loadedCount++;
|
||
else failedCount++;
|
||
|
||
CheckComplete();
|
||
});
|
||
}
|
||
|
||
// 加载Spine
|
||
if (item.SpineAsset != null || !string.IsNullOrEmpty(item.SpineAssetPath))
|
||
{
|
||
PreloadSpine(tableId, item.Id, item, success =>
|
||
{
|
||
if (success) loadedCount++;
|
||
else failedCount++;
|
||
|
||
CheckComplete();
|
||
});
|
||
}
|
||
}
|
||
|
||
void CheckComplete()
|
||
{
|
||
if (loadedCount + failedCount >= totalCount)
|
||
{
|
||
bool allSuccess = failedCount == 0;
|
||
Debug.Log($"[ArtResourceManager] 资源表 {tableId} 预加载完成: 成功={loadedCount}, 失败={failedCount}, 总计={totalCount}");
|
||
NotifyLoadTableComplete(tableId, allSuccess);
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 按Name加载资源表
|
||
/// </summary>
|
||
public void LoadTableByName(string tableName, Action<bool> onComplete = null)
|
||
{
|
||
if (tablesByName.TryGetValue(tableName, out ArtTableSO table))
|
||
{
|
||
LoadTable(table.TableId, onComplete);
|
||
}
|
||
else
|
||
{
|
||
Debug.LogError($"[ArtResourceManager] LoadTableByName失败: 找不到表名称 '{tableName}'");
|
||
onComplete?.Invoke(false);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 通知加载表完成
|
||
/// </summary>
|
||
private void NotifyLoadTableComplete(int tableId, bool success)
|
||
{
|
||
if (loadingTables.ContainsKey(tableId))
|
||
{
|
||
var callbacks = loadingTables[tableId];
|
||
loadingTables.Remove(tableId);
|
||
foreach (var callback in callbacks)
|
||
{
|
||
callback?.Invoke(success);
|
||
}
|
||
}
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region 资源加载(运行时按需加载)
|
||
|
||
/// <summary>
|
||
/// 加载Sprite资源(表ID + 资源项ID)
|
||
/// </summary>
|
||
public void LoadSprite(int tableId, int itemId, Action<Sprite> onComplete)
|
||
{
|
||
LoadSpriteInternal(tableId, itemId, null, onComplete);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 加载Sprite资源(表ID + 资源项Name)
|
||
/// </summary>
|
||
public void LoadSprite(int tableId, string itemName, Action<Sprite> onComplete)
|
||
{
|
||
LoadSpriteInternal(tableId, null, itemName, onComplete);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 加载Sprite资源(表Name + 资源项ID)
|
||
/// </summary>
|
||
public void LoadSprite(string tableName, int itemId, Action<Sprite> onComplete)
|
||
{
|
||
if (!tablesByName.TryGetValue(tableName, out ArtTableSO table))
|
||
{
|
||
Debug.LogError($"[ArtResourceManager] LoadSprite失败: 找不到表名称 '{tableName}'");
|
||
onComplete?.Invoke(null);
|
||
return;
|
||
}
|
||
LoadSpriteInternal(table.TableId, itemId, null, onComplete);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 加载Sprite资源(表Name + 资源项Name)
|
||
/// </summary>
|
||
public void LoadSprite(string tableName, string itemName, Action<Sprite> onComplete)
|
||
{
|
||
if (!tablesByName.TryGetValue(tableName, out ArtTableSO table))
|
||
{
|
||
Debug.LogError($"[ArtResourceManager] LoadSprite失败: 找不到表名称 '{tableName}'");
|
||
onComplete?.Invoke(null);
|
||
return;
|
||
}
|
||
LoadSpriteInternal(table.TableId, null, itemName, onComplete);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 内部加载Sprite实现
|
||
/// </summary>
|
||
private void LoadSpriteInternal(int tableId, int? itemId, string itemName, Action<Sprite> onComplete)
|
||
{
|
||
if (!isInitialized)
|
||
{
|
||
Debug.LogError("[ArtResourceManager] 未初始化,请先调用Initialize()并等待回调完成");
|
||
onComplete?.Invoke(null);
|
||
return;
|
||
}
|
||
|
||
// 从SO中查找Item
|
||
if (!allTables.TryGetValue(tableId, out ArtTableSO table))
|
||
{
|
||
Debug.LogError($"[ArtResourceManager] LoadSprite失败: 找不到表ID {tableId}");
|
||
onComplete?.Invoke(null);
|
||
return;
|
||
}
|
||
|
||
ArtItemData item;
|
||
if (itemId.HasValue)
|
||
{
|
||
item = table.Items.FirstOrDefault(x => x.Id == itemId.Value);
|
||
if (item == null)
|
||
{
|
||
Debug.LogError($"[ArtResourceManager] LoadSprite失败: 资源表{tableId} ({table.TableName}) 中找不到ID为{itemId.Value} 的资源项");
|
||
onComplete?.Invoke(null);
|
||
return;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
item = table.Items.FirstOrDefault(x => x.Name == itemName);
|
||
if (item == null)
|
||
{
|
||
Debug.LogError($"[ArtResourceManager] LoadSprite失败: 资源表{tableId} ({table.TableName}) 中找不到Name为'{itemName}' 的资源项");
|
||
onComplete?.Invoke(null);
|
||
return;
|
||
}
|
||
}
|
||
|
||
string cacheKey = $"{tableId}_{item.Id}";
|
||
|
||
// 检查Sprite缓存
|
||
if (loadedSprites.TryGetValue(cacheKey, out Sprite cachedSprite))
|
||
{
|
||
onComplete?.Invoke(cachedSprite);
|
||
return;
|
||
}
|
||
|
||
// 检查是否正在加载
|
||
if (loadingSprites.ContainsKey(cacheKey))
|
||
{
|
||
loadingSprites[cacheKey].Add(onComplete);
|
||
return;
|
||
}
|
||
|
||
// 开始加载Sprite
|
||
loadingSprites[cacheKey] = new List<Action<Sprite>> { onComplete };
|
||
LoadSpriteAsset(item, sprite =>
|
||
{
|
||
// 缓存结果
|
||
if (sprite != null)
|
||
{
|
||
loadedSprites[cacheKey] = sprite;
|
||
}
|
||
|
||
// 通知所有等待的回调
|
||
var callbacks = loadingSprites[cacheKey];
|
||
loadingSprites.Remove(cacheKey);
|
||
foreach (var callback in callbacks)
|
||
{
|
||
callback?.Invoke(sprite);
|
||
}
|
||
});
|
||
}
|
||
|
||
/// <summary>
|
||
/// 加载Spine资源(表ID + 资源项ID)
|
||
/// </summary>
|
||
public void LoadSpine(int tableId, int itemId, Action<SkeletonDataAsset, string> onComplete)
|
||
{
|
||
LoadSpineInternal(tableId, itemId, null, onComplete);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 加载Spine资源(表ID + 资源项Name)
|
||
/// </summary>
|
||
public void LoadSpine(int tableId, string itemName, Action<SkeletonDataAsset, string> onComplete)
|
||
{
|
||
LoadSpineInternal(tableId, null, itemName, onComplete);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 加载Spine资源(表Name + 资源项ID)
|
||
/// </summary>
|
||
public void LoadSpine(string tableName, int itemId, Action<SkeletonDataAsset, string> onComplete)
|
||
{
|
||
if (!tablesByName.TryGetValue(tableName, out ArtTableSO table))
|
||
{
|
||
Debug.LogError($"[ArtResourceManager] LoadSpine失败: 找不到表名称 '{tableName}'");
|
||
onComplete?.Invoke(null, "");
|
||
return;
|
||
}
|
||
LoadSpineInternal(table.TableId, itemId, null, onComplete);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 加载Spine资源(表Name + 资源项Name)
|
||
/// </summary>
|
||
public void LoadSpine(string tableName, string itemName, Action<SkeletonDataAsset, string> onComplete)
|
||
{
|
||
if (!tablesByName.TryGetValue(tableName, out ArtTableSO table))
|
||
{
|
||
Debug.LogError($"[ArtResourceManager] LoadSpine失败: 找不到表名称 '{tableName}'");
|
||
onComplete?.Invoke(null, "");
|
||
return;
|
||
}
|
||
LoadSpineInternal(table.TableId, null, itemName, onComplete);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 内部加载Spine实现
|
||
/// </summary>
|
||
private void LoadSpineInternal(int tableId, int? itemId, string itemName, Action<SkeletonDataAsset, string> onComplete)
|
||
{
|
||
if (!isInitialized)
|
||
{
|
||
Debug.LogError("[ArtResourceManager] 未初始化,请先调用Initialize()并等待回调完成");
|
||
onComplete?.Invoke(null, "");
|
||
return;
|
||
}
|
||
|
||
// 从SO中查找Item
|
||
if (!allTables.TryGetValue(tableId, out ArtTableSO table))
|
||
{
|
||
Debug.LogError($"[ArtResourceManager] LoadSpine失败: 找不到表ID {tableId}");
|
||
onComplete?.Invoke(null, "");
|
||
return;
|
||
}
|
||
|
||
ArtItemData item;
|
||
if (itemId.HasValue)
|
||
{
|
||
item = table.Items.FirstOrDefault(x => x.Id == itemId.Value);
|
||
if (item == null)
|
||
{
|
||
Debug.LogError($"[ArtResourceManager] LoadSpine失败: 资源表{tableId} ({table.TableName}) 中找不到ID为{itemId.Value} 的资源项");
|
||
onComplete?.Invoke(null, "");
|
||
return;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
item = table.Items.FirstOrDefault(x => x.Name == itemName);
|
||
if (item == null)
|
||
{
|
||
Debug.LogError($"[ArtResourceManager] LoadSpine失败: 资源表{tableId} ({table.TableName}) 中找不到Name为'{itemName}' 的资源项");
|
||
onComplete?.Invoke(null, "");
|
||
return;
|
||
}
|
||
}
|
||
|
||
string cacheKey = $"{tableId}_{item.Id}";
|
||
|
||
// 检查Spine缓存
|
||
if (loadedSpines.TryGetValue(cacheKey, out SkeletonDataAsset cachedSpine))
|
||
{
|
||
onComplete?.Invoke(cachedSpine, item.SpineAnimName);
|
||
return;
|
||
}
|
||
|
||
// 检查是否正在加载
|
||
if (loadingSpines.ContainsKey(cacheKey))
|
||
{
|
||
loadingSpines[cacheKey].Add(spine =>
|
||
{
|
||
onComplete?.Invoke(spine, item.SpineAnimName);
|
||
});
|
||
return;
|
||
}
|
||
|
||
// 开始加载Spine
|
||
loadingSpines[cacheKey] = new List<Action<SkeletonDataAsset>> { spine =>
|
||
{
|
||
onComplete?.Invoke(spine, item.SpineAnimName);
|
||
}};
|
||
|
||
LoadSpineAsset(item, spine =>
|
||
{
|
||
// 缓存结果
|
||
if (spine != null)
|
||
{
|
||
loadedSpines[cacheKey] = spine;
|
||
}
|
||
|
||
// 通知所有等待的回调
|
||
var callbacks = loadingSpines[cacheKey];
|
||
loadingSpines.Remove(cacheKey);
|
||
foreach (var callback in callbacks)
|
||
{
|
||
callback?.Invoke(spine);
|
||
}
|
||
});
|
||
}
|
||
|
||
/// <summary>
|
||
/// 预加载Sprite(内部方法)
|
||
/// </summary>
|
||
private void PreloadSprite(int tableId, int itemId, ArtItemData item, Action<bool> onComplete)
|
||
{
|
||
string cacheKey = $"{tableId}_{itemId}";
|
||
|
||
if (loadedSprites.ContainsKey(cacheKey))
|
||
{
|
||
onComplete?.Invoke(true);
|
||
return;
|
||
}
|
||
|
||
LoadSpriteAsset(item, sprite =>
|
||
{
|
||
if (sprite != null)
|
||
{
|
||
loadedSprites[cacheKey] = sprite;
|
||
onComplete?.Invoke(true);
|
||
}
|
||
else
|
||
{
|
||
onComplete?.Invoke(false);
|
||
}
|
||
});
|
||
}
|
||
|
||
/// <summary>
|
||
/// 预加载Spine(内部方法)
|
||
/// </summary>
|
||
private void PreloadSpine(int tableId, int itemId, ArtItemData item, Action<bool> onComplete)
|
||
{
|
||
string cacheKey = $"{tableId}_{itemId}";
|
||
|
||
if (loadedSpines.ContainsKey(cacheKey))
|
||
{
|
||
onComplete?.Invoke(true);
|
||
return;
|
||
}
|
||
|
||
LoadSpineAsset(item, spine =>
|
||
{
|
||
if (spine != null)
|
||
{
|
||
loadedSpines[cacheKey] = spine;
|
||
onComplete?.Invoke(true);
|
||
}
|
||
else
|
||
{
|
||
onComplete?.Invoke(false);
|
||
}
|
||
});
|
||
}
|
||
|
||
/// <summary>
|
||
/// 加载Sprite资源(同时支持Editor和Runtime模式)
|
||
/// Editor模式:优先使用Sprite引用
|
||
/// Runtime模式:使用SpritePath通过GameFramework加载
|
||
/// </summary>
|
||
private void LoadSpriteAsset(ArtItemData item, Action<Sprite> onComplete)
|
||
{
|
||
// Editor模式:直接使用引用
|
||
if (item.Sprite != null)
|
||
{
|
||
onComplete?.Invoke(item.Sprite);
|
||
return;
|
||
}
|
||
|
||
// Runtime模式:需要通过路径加载
|
||
if (string.IsNullOrEmpty(item.SpritePath))
|
||
{
|
||
Debug.LogError($"[ArtResourceManager] Sprite资源引用和路径都为空: {item.Name}");
|
||
onComplete?.Invoke(null);
|
||
return;
|
||
}
|
||
|
||
var loadCallbacks = new LoadAssetCallbacks(
|
||
// 成功回调
|
||
(assetName, asset, duration, userData) =>
|
||
{
|
||
var sprite = asset as Sprite;
|
||
if (sprite != null)
|
||
{
|
||
onComplete?.Invoke(sprite);
|
||
}
|
||
else
|
||
{
|
||
Debug.LogError($"[ArtResourceManager] 加载Sprite失败,资源类型错误: {item.SpritePath}");
|
||
onComplete?.Invoke(null);
|
||
}
|
||
},
|
||
// 失败回调
|
||
(assetName, status, errorMessage, userData) =>
|
||
{
|
||
Debug.LogError($"[ArtResourceManager] 加载Sprite异常 [{item.SpritePath}]: {errorMessage}");
|
||
onComplete?.Invoke(null);
|
||
}
|
||
);
|
||
|
||
GameEntry.Resource.LoadAsset(item.SpritePath, typeof(Sprite), loadCallbacks);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 加载Spine资源(同时支持Editor和Runtime模式)
|
||
/// Editor模式:优先使用SpineAsset引用
|
||
/// Runtime模式:使用SpineAssetPath通过GameFramework加载
|
||
/// </summary>
|
||
private void LoadSpineAsset(ArtItemData item, Action<SkeletonDataAsset> onComplete)
|
||
{
|
||
// Editor模式:直接使用引用
|
||
if (item.SpineAsset != null)
|
||
{
|
||
onComplete?.Invoke(item.SpineAsset);
|
||
return;
|
||
}
|
||
|
||
// Runtime模式:需要通过路径加载
|
||
if (string.IsNullOrEmpty(item.SpineAssetPath))
|
||
{
|
||
Debug.LogError($"[ArtResourceManager] Spine资源引用和路径都为空: {item.Name}");
|
||
onComplete?.Invoke(null);
|
||
return;
|
||
}
|
||
|
||
var loadCallbacks = new LoadAssetCallbacks(
|
||
// 成功回调
|
||
(assetName, asset, duration, userData) =>
|
||
{
|
||
var spine = asset as SkeletonDataAsset;
|
||
if (spine != null)
|
||
{
|
||
onComplete?.Invoke(spine);
|
||
}
|
||
else
|
||
{
|
||
Debug.LogError($"[ArtResourceManager] 加载Spine失败,资源类型错误: {item.SpineAssetPath}");
|
||
onComplete?.Invoke(null);
|
||
}
|
||
},
|
||
// 失败回调
|
||
(assetName, status, errorMessage, userData) =>
|
||
{
|
||
Debug.LogError($"[ArtResourceManager] 加载Spine异常 [{item.SpineAssetPath}]: {errorMessage}");
|
||
onComplete?.Invoke(null);
|
||
}
|
||
);
|
||
|
||
GameEntry.Resource.LoadAsset(item.SpineAssetPath, typeof(SkeletonDataAsset), loadCallbacks);
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region 查询方法
|
||
|
||
/// <summary>
|
||
/// 检查是否已初始化完成
|
||
/// </summary>
|
||
public bool IsInitialized => isInitialized;
|
||
|
||
/// <summary>
|
||
/// 获取Spine动画名称(表ID + 资源项ID)
|
||
/// </summary>
|
||
public string GetSpineAnimName(int tableId, int itemId)
|
||
{
|
||
return GetSpineAnimNameInternal(tableId, itemId, null);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取Spine动画名称(表ID + 资源项Name)
|
||
/// </summary>
|
||
public string GetSpineAnimName(int tableId, string itemName)
|
||
{
|
||
return GetSpineAnimNameInternal(tableId, null, itemName);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取Spine动画名称(表Name + 资源项ID)
|
||
/// </summary>
|
||
public string GetSpineAnimName(string tableName, int itemId)
|
||
{
|
||
if (!tablesByName.TryGetValue(tableName, out ArtTableSO table))
|
||
{
|
||
Debug.LogError($"[ArtResourceManager] GetSpineAnimName失败: 找不到表名称 '{tableName}'");
|
||
return "";
|
||
}
|
||
return GetSpineAnimNameInternal(table.TableId, itemId, null);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取Spine动画名称(表Name + 资源项Name)
|
||
/// </summary>
|
||
public string GetSpineAnimName(string tableName, string itemName)
|
||
{
|
||
if (!tablesByName.TryGetValue(tableName, out ArtTableSO table))
|
||
{
|
||
Debug.LogError($"[ArtResourceManager] GetSpineAnimName失败: 找不到表名称 '{tableName}'");
|
||
return "";
|
||
}
|
||
return GetSpineAnimNameInternal(table.TableId, null, itemName);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 内部获取Spine动画名称实现
|
||
/// </summary>
|
||
private string GetSpineAnimNameInternal(int tableId, int? itemId, string itemName)
|
||
{
|
||
if (!allTables.TryGetValue(tableId, out ArtTableSO table))
|
||
{
|
||
Debug.LogError($"[ArtResourceManager] GetSpineAnimName失败: 找不到表ID {tableId}");
|
||
return "";
|
||
}
|
||
|
||
ArtItemData item;
|
||
if (itemId.HasValue)
|
||
{
|
||
item = table.Items.FirstOrDefault(x => x.Id == itemId.Value);
|
||
if (item == null)
|
||
{
|
||
Debug.LogError($"[ArtResourceManager] GetSpineAnimName失败: 资源表{tableId} ({table.TableName}) 中找不到ID为{itemId.Value} 的资源项");
|
||
return "";
|
||
}
|
||
}
|
||
else
|
||
{
|
||
item = table.Items.FirstOrDefault(x => x.Name == itemName);
|
||
if (item == null)
|
||
{
|
||
Debug.LogError($"[ArtResourceManager] GetSpineAnimName失败: 资源表{tableId} ({table.TableName}) 中找不到Name为'{itemName}' 的资源项");
|
||
return "";
|
||
}
|
||
}
|
||
|
||
return item.SpineAnimName ?? "";
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region 工具方法
|
||
|
||
/// <summary>
|
||
/// 检查资源表是否存在
|
||
/// </summary>
|
||
public bool HasTable(int tableId)
|
||
{
|
||
return allTables.ContainsKey(tableId);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 检查资源表是否存在(按Name)
|
||
/// </summary>
|
||
public bool HasTable(string tableName)
|
||
{
|
||
return tablesByName.ContainsKey(tableName);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取资源表信息(不加载资源)
|
||
/// </summary>
|
||
public ArtTableSO GetTable(int tableId)
|
||
{
|
||
allTables.TryGetValue(tableId, out ArtTableSO table);
|
||
return table;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取资源表信息(按Name,不加载资源)
|
||
/// </summary>
|
||
public ArtTableSO GetTable(string tableName)
|
||
{
|
||
tablesByName.TryGetValue(tableName, out ArtTableSO table);
|
||
return table;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 清空指定表的所有资源缓存(保留SO)
|
||
/// </summary>
|
||
public void ClearTableCache(int tableId)
|
||
{
|
||
int clearedCount = 0;
|
||
|
||
// 清理Sprite缓存
|
||
var spriteKeys = loadedSprites.Keys.Where(k => k.StartsWith($"{tableId}_")).ToList();
|
||
foreach (var key in spriteKeys)
|
||
{
|
||
loadedSprites.Remove(key);
|
||
clearedCount++;
|
||
}
|
||
|
||
// 清理Spine缓存
|
||
var spineKeys = loadedSpines.Keys.Where(k => k.StartsWith($"{tableId}_")).ToList();
|
||
foreach (var key in spineKeys)
|
||
{
|
||
loadedSpines.Remove(key);
|
||
clearedCount++;
|
||
}
|
||
|
||
Debug.Log($"[ArtResourceManager] 清空资源表 {tableId} 缓存: {clearedCount} 项资源");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 清空所有资源缓存(保留SO)
|
||
/// </summary>
|
||
public void ClearAllCache()
|
||
{
|
||
int spriteCount = loadedSprites.Count;
|
||
int spineCount = loadedSpines.Count;
|
||
|
||
loadedSprites.Clear();
|
||
loadedSpines.Clear();
|
||
|
||
Debug.Log($"[ArtResourceManager] 清空所有资源缓存: {spriteCount} 个Sprite, {spineCount} 个Spine(SO保留)");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取缓存统计信息
|
||
/// </summary>
|
||
public string GetCacheInfo()
|
||
{
|
||
int totalItems = allTables.Values.Sum(table => table.Items.Count);
|
||
|
||
return $"SO缓存: {allTables.Count} 个表 ({totalItems} 项资源定义)\n" +
|
||
$"Sprite缓存: {loadedSprites.Count} 个\n" +
|
||
$"Spine缓存: {loadedSpines.Count} 个";
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取所有表ID
|
||
/// </summary>
|
||
public List<int> GetAllTableIds()
|
||
{
|
||
return new List<int>(allTables.Keys);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取所有表名称
|
||
/// </summary>
|
||
public List<string> GetAllTableNames()
|
||
{
|
||
return new List<string>(tablesByName.Keys);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取Sprite资源的完整路径
|
||
/// </summary>
|
||
/// <param name="tableId">表ID</param>
|
||
/// <param name="itemId">资源项ID</param>
|
||
/// <returns>资源完整路径,如果找不到返回null</returns>
|
||
public string GetSpritePath(int tableId, int itemId)
|
||
{
|
||
if (!isInitialized)
|
||
{
|
||
Debug.LogError("[ArtResourceManager] 未初始化,请先调用Initialize()并等待回调完成");
|
||
return null;
|
||
}
|
||
|
||
if (!allTables.TryGetValue(tableId, out ArtTableSO table))
|
||
{
|
||
Debug.LogError($"[ArtResourceManager] GetSpritePath失败: 找不到表ID {tableId}");
|
||
return null;
|
||
}
|
||
|
||
var item = table.Items.FirstOrDefault(x => x.Id == itemId);
|
||
if (item == null)
|
||
{
|
||
Debug.LogError($"[ArtResourceManager] GetSpritePath失败: 表{tableId}中找不到ID为{itemId}的资源项");
|
||
return null;
|
||
}
|
||
|
||
if (string.IsNullOrEmpty(item.SpritePath))
|
||
{
|
||
Debug.LogWarning($"[ArtResourceManager] 资源项 {tableId}_{itemId} 没有配置Sprite路径");
|
||
return null;
|
||
}
|
||
|
||
return item.SpritePath;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取Sprite资源的完整路径(表ID + 资源项名称)
|
||
/// </summary>
|
||
/// <param name="tableId">表ID</param>
|
||
/// <param name="itemName">资源项名称</param>
|
||
/// <returns>资源完整路径,如果找不到返回null</returns>
|
||
public string GetSpritePath(int tableId, string itemName)
|
||
{
|
||
if (!isInitialized)
|
||
{
|
||
Debug.LogError("[ArtResourceManager] 未初始化,请先调用Initialize()并等待回调完成");
|
||
return null;
|
||
}
|
||
|
||
if (!allTables.TryGetValue(tableId, out ArtTableSO table))
|
||
{
|
||
Debug.LogError($"[ArtResourceManager] GetSpritePath失败: 找不到表ID {tableId}");
|
||
return null;
|
||
}
|
||
|
||
var item = table.Items.FirstOrDefault(x => x.Name == itemName);
|
||
if (item == null)
|
||
{
|
||
Debug.LogError($"[ArtResourceManager] GetSpritePath失败: 表{tableId}中找不到名称为'{itemName}'的资源项");
|
||
return null;
|
||
}
|
||
|
||
if (string.IsNullOrEmpty(item.SpritePath))
|
||
{
|
||
Debug.LogWarning($"[ArtResourceManager] 资源项 {tableId}/{itemName} 没有配置Sprite路径");
|
||
return null;
|
||
}
|
||
|
||
return item.SpritePath;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取Sprite资源的完整路径(表名称 + 资源项ID)
|
||
/// </summary>
|
||
/// <param name="tableName">表名称</param>
|
||
/// <param name="itemId">资源项ID</param>
|
||
/// <returns>资源完整路径,如果找不到返回null</returns>
|
||
public string GetSpritePath(string tableName, int itemId)
|
||
{
|
||
if (!isInitialized)
|
||
{
|
||
Debug.LogError("[ArtResourceManager] 未初始化,请先调用Initialize()并等待回调完成");
|
||
return null;
|
||
}
|
||
|
||
if (!tablesByName.TryGetValue(tableName, out ArtTableSO table))
|
||
{
|
||
Debug.LogError($"[ArtResourceManager] GetSpritePath失败: 找不到表名 {tableName}");
|
||
return null;
|
||
}
|
||
|
||
var item = table.Items.FirstOrDefault(x => x.Id == itemId);
|
||
if (item == null)
|
||
{
|
||
Debug.LogError($"[ArtResourceManager] GetSpritePath失败: 表{tableName}中找不到ID为{itemId}的资源项");
|
||
return null;
|
||
}
|
||
|
||
if (string.IsNullOrEmpty(item.SpritePath))
|
||
{
|
||
Debug.LogWarning($"[ArtResourceManager] 资源项 {tableName}/{itemId} 没有配置Sprite路径");
|
||
return null;
|
||
}
|
||
|
||
return item.SpritePath;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取Sprite资源的完整路径(按名称查询)
|
||
/// </summary>
|
||
/// <param name="tableName">表名称</param>
|
||
/// <param name="itemName">资源项名称</param>
|
||
/// <returns>资源完整路径,如果找不到返回null</returns>
|
||
public string GetSpritePath(string tableName, string itemName)
|
||
{
|
||
if (!isInitialized)
|
||
{
|
||
Debug.LogError("[ArtResourceManager] 未初始化,请先调用Initialize()并等待回调完成");
|
||
return null;
|
||
}
|
||
|
||
if (!tablesByName.TryGetValue(tableName, out ArtTableSO table))
|
||
{
|
||
Debug.LogError($"[ArtResourceManager] GetSpritePath失败: 找不到表名 {tableName}");
|
||
return null;
|
||
}
|
||
|
||
var item = table.Items.FirstOrDefault(x => x.Name == itemName);
|
||
if (item == null)
|
||
{
|
||
Debug.LogError($"[ArtResourceManager] GetSpritePath失败: 表{tableName}中找不到名称为'{itemName}'的资源项");
|
||
return null;
|
||
}
|
||
|
||
if (string.IsNullOrEmpty(item.SpritePath))
|
||
{
|
||
Debug.LogWarning($"[ArtResourceManager] 资源项 {tableName}/{itemName} 没有配置Sprite路径");
|
||
return null;
|
||
}
|
||
|
||
return item.SpritePath;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取SkeletonDataAsset资源的完整路径
|
||
/// </summary>
|
||
/// <param name="tableId">表ID</param>
|
||
/// <param name="itemId">资源项ID</param>
|
||
/// <returns>资源完整路径,如果找不到返回null</returns>
|
||
public string GetSpinePath(int tableId, int itemId)
|
||
{
|
||
if (!isInitialized)
|
||
{
|
||
Debug.LogError("[ArtResourceManager] 未初始化,请先调用Initialize()并等待回调完成");
|
||
return null;
|
||
}
|
||
|
||
if (!allTables.TryGetValue(tableId, out ArtTableSO table))
|
||
{
|
||
Debug.LogError($"[ArtResourceManager] GetSpinePath失败: 找不到表ID {tableId}");
|
||
return null;
|
||
}
|
||
|
||
var item = table.Items.FirstOrDefault(x => x.Id == itemId);
|
||
if (item == null)
|
||
{
|
||
Debug.LogError($"[ArtResourceManager] GetSpinePath失败: 表{tableId}中找不到ID为{itemId}的资源项");
|
||
return null;
|
||
}
|
||
|
||
if (string.IsNullOrEmpty(item.SpineAssetPath))
|
||
{
|
||
Debug.LogWarning($"[ArtResourceManager] 资源项 {tableId}_{itemId} 没有配置Spine路径");
|
||
return null;
|
||
}
|
||
|
||
return item.SpineAssetPath;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取SkeletonDataAsset资源的完整路径(表ID + 资源项名称)
|
||
/// </summary>
|
||
/// <param name="tableId">表ID</param>
|
||
/// <param name="itemName">资源项名称</param>
|
||
/// <returns>资源完整路径,如果找不到返回null</returns>
|
||
public string GetSpinePath(int tableId, string itemName)
|
||
{
|
||
if (!isInitialized)
|
||
{
|
||
Debug.LogError("[ArtResourceManager] 未初始化,请先调用Initialize()并等待回调完成");
|
||
return null;
|
||
}
|
||
|
||
if (!allTables.TryGetValue(tableId, out ArtTableSO table))
|
||
{
|
||
Debug.LogError($"[ArtResourceManager] GetSpinePath失败: 找不到表ID {tableId}");
|
||
return null;
|
||
}
|
||
|
||
var item = table.Items.FirstOrDefault(x => x.Name == itemName);
|
||
if (item == null)
|
||
{
|
||
Debug.LogError($"[ArtResourceManager] GetSpinePath失败: 表{tableId}中找不到名称为'{itemName}'的资源项");
|
||
return null;
|
||
}
|
||
|
||
if (string.IsNullOrEmpty(item.SpineAssetPath))
|
||
{
|
||
Debug.LogWarning($"[ArtResourceManager] 资源项 {tableId}/{itemName} 没有配置Spine路径");
|
||
return null;
|
||
}
|
||
|
||
return item.SpineAssetPath;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取SkeletonDataAsset资源的完整路径(表名称 + 资源项ID)
|
||
/// </summary>
|
||
/// <param name="tableName">表名称</param>
|
||
/// <param name="itemId">资源项ID</param>
|
||
/// <returns>资源完整路径,如果找不到返回null</returns>
|
||
public string GetSpinePath(string tableName, int itemId)
|
||
{
|
||
if (!isInitialized)
|
||
{
|
||
Debug.LogError("[ArtResourceManager] 未初始化,请先调用Initialize()并等待回调完成");
|
||
return null;
|
||
}
|
||
|
||
if (!tablesByName.TryGetValue(tableName, out ArtTableSO table))
|
||
{
|
||
Debug.LogError($"[ArtResourceManager] GetSpinePath失败: 找不到表名 {tableName}");
|
||
return null;
|
||
}
|
||
|
||
var item = table.Items.FirstOrDefault(x => x.Id == itemId);
|
||
if (item == null)
|
||
{
|
||
Debug.LogError($"[ArtResourceManager] GetSpinePath失败: 表{tableName}中找不到ID为{itemId}的资源项");
|
||
return null;
|
||
}
|
||
|
||
if (string.IsNullOrEmpty(item.SpineAssetPath))
|
||
{
|
||
Debug.LogWarning($"[ArtResourceManager] 资源项 {tableName}/{itemId} 没有配置Spine路径");
|
||
return null;
|
||
}
|
||
|
||
return item.SpineAssetPath;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取SkeletonDataAsset资源的完整路径(按名称查询)
|
||
/// </summary>
|
||
/// <param name="tableName">表名称</param>
|
||
/// <param name="itemName">资源项名称</param>
|
||
/// <returns>资源完整路径,如果找不到返回null</returns>
|
||
public string GetSpinePath(string tableName, string itemName)
|
||
{
|
||
if (!isInitialized)
|
||
{
|
||
Debug.LogError("[ArtResourceManager] 未初始化,请先调用Initialize()并等待回调完成");
|
||
return null;
|
||
}
|
||
|
||
if (!tablesByName.TryGetValue(tableName, out ArtTableSO table))
|
||
{
|
||
Debug.LogError($"[ArtResourceManager] GetSpinePath失败: 找不到表名 {tableName}");
|
||
return null;
|
||
}
|
||
|
||
var item = table.Items.FirstOrDefault(x => x.Name == itemName);
|
||
if (item == null)
|
||
{
|
||
Debug.LogError($"[ArtResourceManager] GetSpinePath失败: 表{tableName}中找不到名称为'{itemName}'的资源项");
|
||
return null;
|
||
}
|
||
|
||
if (string.IsNullOrEmpty(item.SpineAssetPath))
|
||
{
|
||
Debug.LogWarning($"[ArtResourceManager] 资源项 {tableName}/{itemName} 没有配置Spine路径");
|
||
return null;
|
||
}
|
||
|
||
return item.SpineAssetPath;
|
||
}
|
||
|
||
#endregion
|
||
}
|
||
}
|