diff --git a/Art_Atlas/AtlasConfig.json b/Art_Atlas/AtlasConfig.json index 372e5202..ff628591 100644 --- a/Art_Atlas/AtlasConfig.json +++ b/Art_Atlas/AtlasConfig.json @@ -50,6 +50,24 @@ "Assets/Art_SubModule/Art_Resource/Art_UISprites/Emoji/cat_biaoqing_3.png", "Assets/Art_SubModule/Art_Resource/Art_UISprites/Emoji/cat_biaoqing_4.png" ] + }, + { + "Name": "headFrameAtlas", + "SpritePaths": [ + "Assets/Art_SubModule/Art_Resource/Art_UISprites/Frame/HeadFrame0.png", + "Assets/Art_SubModule/Art_Resource/Art_UISprites/Frame/HeadFrame1.png", + "Assets/Art_SubModule/Art_Resource/Art_UISprites/Frame/HeadFrame10.png", + "Assets/Art_SubModule/Art_Resource/Art_UISprites/Frame/HeadFrame11.png", + "Assets/Art_SubModule/Art_Resource/Art_UISprites/Frame/HeadFrame12.png", + "Assets/Art_SubModule/Art_Resource/Art_UISprites/Frame/HeadFrame2.png", + "Assets/Art_SubModule/Art_Resource/Art_UISprites/Frame/HeadFrame3.png", + "Assets/Art_SubModule/Art_Resource/Art_UISprites/Frame/HeadFrame4.png", + "Assets/Art_SubModule/Art_Resource/Art_UISprites/Frame/HeadFrame5.png", + "Assets/Art_SubModule/Art_Resource/Art_UISprites/Frame/HeadFrame6.png", + "Assets/Art_SubModule/Art_Resource/Art_UISprites/Frame/HeadFrame7.png", + "Assets/Art_SubModule/Art_Resource/Art_UISprites/Frame/HeadFrame8.png", + "Assets/Art_SubModule/Art_Resource/Art_UISprites/Frame/HeadFrame9.png" + ] } ] } \ No newline at end of file diff --git a/Art_Atlas/emojiAtlas.spriteatlas b/Art_Atlas/emojiAtlas.spriteatlas index db5e0750..902828e4 100644 --- a/Art_Atlas/emojiAtlas.spriteatlas +++ b/Art_Atlas/emojiAtlas.spriteatlas @@ -34,9 +34,22 @@ SpriteAtlas: m_IgnorePlatformSupport: 0 m_AndroidETC2FallbackOverride: 0 m_ForceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + m_BuildTarget: Android + m_MaxTextureSize: 1024 + m_ResizeAlgorithm: 0 + m_TextureFormat: 50 + m_TextureCompression: 1 + m_CompressionQuality: 50 + m_CrunchedCompression: 0 + m_AllowsAlphaSplitting: 0 + m_Overridden: 1 + m_IgnorePlatformSupport: 0 + m_AndroidETC2FallbackOverride: 0 + m_ForceMaximumCompressionQuality_BC6H_BC7: 0 packingSettings: serializedVersion: 2 - padding: 2 + padding: 4 blockOffset: 1 allowAlphaSplitting: 0 enableRotation: 0 diff --git a/Art_Atlas/headAtlas.spriteatlas b/Art_Atlas/headAtlas.spriteatlas index 9bf34528..21009e2a 100644 --- a/Art_Atlas/headAtlas.spriteatlas +++ b/Art_Atlas/headAtlas.spriteatlas @@ -34,13 +34,26 @@ SpriteAtlas: m_IgnorePlatformSupport: 0 m_AndroidETC2FallbackOverride: 0 m_ForceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + m_BuildTarget: Android + m_MaxTextureSize: 2048 + m_ResizeAlgorithm: 0 + m_TextureFormat: 50 + m_TextureCompression: 1 + m_CompressionQuality: 50 + m_CrunchedCompression: 0 + m_AllowsAlphaSplitting: 0 + m_Overridden: 1 + m_IgnorePlatformSupport: 0 + m_AndroidETC2FallbackOverride: 0 + m_ForceMaximumCompressionQuality_BC6H_BC7: 0 packingSettings: serializedVersion: 2 padding: 8 blockOffset: 1 allowAlphaSplitting: 0 enableRotation: 0 - enableTightPacking: 1 + enableTightPacking: 0 enableAlphaDilation: 0 secondaryTextureSettings: {} variantMultiplier: 1 diff --git a/Art_Atlas/headFrameAtlas.spriteatlas b/Art_Atlas/headFrameAtlas.spriteatlas new file mode 100644 index 00000000..38054c4d --- /dev/null +++ b/Art_Atlas/headFrameAtlas.spriteatlas @@ -0,0 +1,122 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!687078895 &4343727234628468602 +SpriteAtlas: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: headFrameAtlas + m_EditorData: + serializedVersion: 2 + textureSettings: + serializedVersion: 2 + anisoLevel: 0 + compressionQuality: 0 + maxTextureSize: 0 + textureCompression: 0 + filterMode: 1 + generateMipMaps: 0 + readable: 0 + crunchedCompression: 0 + sRGB: 1 + platformSettings: + - serializedVersion: 3 + m_BuildTarget: DefaultTexturePlatform + m_MaxTextureSize: 2048 + m_ResizeAlgorithm: 0 + m_TextureFormat: -1 + m_TextureCompression: 1 + m_CompressionQuality: 50 + m_CrunchedCompression: 0 + m_AllowsAlphaSplitting: 0 + m_Overridden: 0 + m_IgnorePlatformSupport: 0 + m_AndroidETC2FallbackOverride: 0 + m_ForceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + m_BuildTarget: Android + m_MaxTextureSize: 1024 + m_ResizeAlgorithm: 0 + m_TextureFormat: 50 + m_TextureCompression: 1 + m_CompressionQuality: 50 + m_CrunchedCompression: 0 + m_AllowsAlphaSplitting: 0 + m_Overridden: 1 + m_IgnorePlatformSupport: 0 + m_AndroidETC2FallbackOverride: 0 + m_ForceMaximumCompressionQuality_BC6H_BC7: 0 + packingSettings: + serializedVersion: 2 + padding: 2 + blockOffset: 1 + allowAlphaSplitting: 0 + enableRotation: 0 + enableTightPacking: 0 + enableAlphaDilation: 0 + secondaryTextureSettings: {} + variantMultiplier: 1 + packables: + - {fileID: 21300000, guid: 17e8a70e4a702d34e8cbbe4dc68960cf, type: 3} + - {fileID: 21300000, guid: 8dc274a70830dc24dbae19d83221bccb, type: 3} + - {fileID: 21300000, guid: 58a4e1366832b1d45a68465fa197c8d7, type: 3} + - {fileID: 21300000, guid: bc76e5879bd3a884a8bfba4761946766, type: 3} + - {fileID: 21300000, guid: 0ac7b61698990e243ac23ee41ebc5a06, type: 3} + - {fileID: 21300000, guid: d9d6c727d0759b24c8795d0b528f07ad, type: 3} + - {fileID: 21300000, guid: 4f796c10aeb92f34c96e80cd30fe6e43, type: 3} + - {fileID: 21300000, guid: 9273afdf62366184fbd1c91c50b247e7, type: 3} + - {fileID: 21300000, guid: a8c390e19f520344fad88b5f81477850, type: 3} + - {fileID: 21300000, guid: afce391990a5efd4dbf8514468b2e740, type: 3} + - {fileID: 21300000, guid: 7295559c7c88e6841ac1501db834a613, type: 3} + - {fileID: 21300000, guid: ecb723ab9cbe8e44cb567a31a93be8f4, type: 3} + - {fileID: 21300000, guid: aa6573af9a413a64db683a8beabb7da8, type: 3} + bindAsDefault: 1 + isAtlasV2: 0 + cachedData: {fileID: 0} + packedSpriteRenderDataKeys: + - 4f796c10aeb92f34c96e80cd30fe6e43: 21300000 + - a8c390e19f520344fad88b5f81477850: 21300000 + - 0ac7b61698990e243ac23ee41ebc5a06: 21300000 + - 58a4e1366832b1d45a68465fa197c8d7: 21300000 + - d9d6c727d0759b24c8795d0b528f07ad: 21300000 + - bc76e5879bd3a884a8bfba4761946766: 21300000 + - 8dc274a70830dc24dbae19d83221bccb: 21300000 + - afce391990a5efd4dbf8514468b2e740: 21300000 + - ecb723ab9cbe8e44cb567a31a93be8f4: 21300000 + - 7295559c7c88e6841ac1501db834a613: 21300000 + - 17e8a70e4a702d34e8cbbe4dc68960cf: 21300000 + - aa6573af9a413a64db683a8beabb7da8: 21300000 + - 9273afdf62366184fbd1c91c50b247e7: 21300000 + m_MasterAtlas: {fileID: 0} + m_PackedSprites: + - {fileID: 21300000, guid: 4f796c10aeb92f34c96e80cd30fe6e43, type: 3} + - {fileID: 21300000, guid: a8c390e19f520344fad88b5f81477850, type: 3} + - {fileID: 21300000, guid: 0ac7b61698990e243ac23ee41ebc5a06, type: 3} + - {fileID: 21300000, guid: 58a4e1366832b1d45a68465fa197c8d7, type: 3} + - {fileID: 21300000, guid: d9d6c727d0759b24c8795d0b528f07ad, type: 3} + - {fileID: 21300000, guid: bc76e5879bd3a884a8bfba4761946766, type: 3} + - {fileID: 21300000, guid: 8dc274a70830dc24dbae19d83221bccb, type: 3} + - {fileID: 21300000, guid: afce391990a5efd4dbf8514468b2e740, type: 3} + - {fileID: 21300000, guid: ecb723ab9cbe8e44cb567a31a93be8f4, type: 3} + - {fileID: 21300000, guid: 7295559c7c88e6841ac1501db834a613, type: 3} + - {fileID: 21300000, guid: 17e8a70e4a702d34e8cbbe4dc68960cf, type: 3} + - {fileID: 21300000, guid: aa6573af9a413a64db683a8beabb7da8, type: 3} + - {fileID: 21300000, guid: 9273afdf62366184fbd1c91c50b247e7, type: 3} + m_PackedSpriteNamesToIndex: + - HeadFrame3 + - HeadFrame5 + - HeadFrame12 + - HeadFrame10 + - HeadFrame2 + - HeadFrame11 + - HeadFrame1 + - HeadFrame6 + - HeadFrame8 + - HeadFrame7 + - HeadFrame0 + - HeadFrame9 + - HeadFrame4 + m_RenderDataMap: {} + m_Tag: headFrameAtlas + m_IsVariant: 0 diff --git a/Art_Atlas/headFrameAtlas.spriteatlas.meta b/Art_Atlas/headFrameAtlas.spriteatlas.meta new file mode 100644 index 00000000..03268d3e --- /dev/null +++ b/Art_Atlas/headFrameAtlas.spriteatlas.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 87f1b4da111407e4cb21d8251737e99e +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 4343727234628468602 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Art_Scripts/ArtResourceManager.cs b/Art_Scripts/ArtResourceManager.cs index d81601c3..b6120b2e 100644 --- a/Art_Scripts/ArtResourceManager.cs +++ b/Art_Scripts/ArtResourceManager.cs @@ -120,8 +120,9 @@ namespace CrazyMaple #region 初始化 /// - /// 初始化:加载所有ArtTableSO(异步回调方式) - /// 建议在ProcedurePreload中调用,并等待回调完成 + /// 初始化资源管理器 + /// Editor模式:延迟加载SO(避免反序列化资源引用导致卡顿) + /// Runtime模式:加载所有SO(Runtime下加载SO很快,不会有性能问题) /// /// 初始化完成回调(true=成功,false=失败) public void Initialize(Action onComplete = null) @@ -147,24 +148,26 @@ namespace CrazyMaple } var startTime = Time.realtimeSinceStartup; - Debug.Log("[ArtResourceManager] 开始加载所有ArtTableSO..."); - // Editor和Runtime统一使用GameEntry.Resource.LoadAsset - LoadAllTables(success => +#if UNITY_EDITOR + // Editor模式:延迟加载(避免反序列化大量资源引用) + Debug.Log("[ArtResourceManager] 开始初始化 ArtResourceManager(Editor延迟加载模式)..."); + LoadManifestOnly(success => { var duration = (Time.realtimeSinceStartup - startTime) * 1000f; if (success) { isInitialized = true; - Debug.Log($"[ArtResourceManager] SO初始化完成: {allTables.Count} 个表,耗时 {duration:F2}ms"); + Debug.Log($"[ArtResourceManager] 初始化完成(Editor延迟加载): 索引了 {manifest.tablePaths.Length} 个表,耗时 {duration:F2}ms"); + Debug.Log($"[ArtResourceManager] SO将在首次使用时按需加载"); - // 自动预加载配置的表 + // 自动预加载配置的表(如果有) AutoPreloadTables(); } else { - Debug.LogError("[ArtResourceManager] SO初始化失败"); + Debug.LogError("[ArtResourceManager] 初始化失败"); } // 通知所有等待的回调 @@ -175,6 +178,183 @@ namespace CrazyMaple callback?.Invoke(success); } }); +#else + // Runtime模式:直接加载所有SO(Runtime下加载SO很快,不会反序列化资源引用) + Debug.Log("[ArtResourceManager] 开始初始化 ArtResourceManager(Runtime全量加载模式)..."); + LoadAllTables(success => + { + var duration = (Time.realtimeSinceStartup - startTime) * 1000f; + + if (success) + { + isInitialized = true; + Debug.Log($"[ArtResourceManager] 初始化完成(Runtime全量加载): 加载了 {allTables.Count} 个表,耗时 {duration:F2}ms"); + + // 自动预加载配置的表(如果有) + AutoPreloadTables(); + } + else + { + Debug.LogError("[ArtResourceManager] 初始化失败"); + } + + // 通知所有等待的回调 + var callbacks = new List>(initializeCallbacks); + initializeCallbacks.Clear(); + foreach (var callback in callbacks) + { + callback?.Invoke(success); + } + }); +#endif + } + + /// + /// 只加载manifest索引文件,不加载SO(延迟加载优化) + /// + private void LoadManifestOnly(Action 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(manifestAsset.text); + + if (manifest == null || manifest.tablePaths == null || manifest.tablePaths.Length == 0) + { + Debug.LogError("[ArtResourceManager] 索引文件为空,没有找到任何SO"); + onComplete?.Invoke(false); + return; + } + + Debug.Log($"[ArtResourceManager] 成功加载manifest索引: {manifest.tablePaths.Length} 个SO将按需加载"); + onComplete?.Invoke(true); + }, + // 失败回调 + (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); + } + + /// + /// 尝试同步加载表(用于同步API如GetSpritePath) + /// + private bool TrySyncLoadTable(string tableName, out ArtTableSO table) + { + table = null; + + // 检查manifest中是否有该表 + if (manifest == null || manifest.tablePaths == null) + { + return false; + } + + // 查找SO路径 + string soPath = null; + foreach (var path in manifest.tablePaths) + { + if (path.Contains(tableName)) + { + soPath = path; + break; + } + } + + if (string.IsNullOrEmpty(soPath)) + { + return false; + } + + // 同步加载SO + Debug.Log($"[ArtResourceManager] 同步按需加载SO: {tableName}"); + +#if UNITY_EDITOR + // Editor模式下使用AssetDatabase同步加载 + var so = UnityEditor.AssetDatabase.LoadAssetAtPath(soPath); + if (so != null) + { + RegisterTable(so, soPath); + table = so; + return true; + } +#else + // Runtime模式下无法同步加载,返回false + Debug.LogWarning($"[ArtResourceManager] Runtime模式不支持同步加载表: {tableName},请使用异步API"); +#endif + + return false; + } + + /// + /// 按需加载单个SO(如果还没加载) + /// + private void LoadTableSO(string tableName, Action onComplete) + { + // 检查是否已加载 + if (tablesByName.TryGetValue(tableName, out var existingTable)) + { + onComplete?.Invoke(true); + return; + } + + // 从manifest中查找路径 + if (manifest == null || manifest.tablePaths == null) + { + Debug.LogError($"[ArtResourceManager] Manifest未加载,无法加载表 {tableName}"); + onComplete?.Invoke(false); + return; + } + + // 查找SO路径(通过文件名匹配) + string soPath = null; + foreach (var path in manifest.tablePaths) + { + if (path.Contains(tableName)) + { + soPath = path; + break; + } + } + + if (string.IsNullOrEmpty(soPath)) + { + Debug.LogError($"[ArtResourceManager] 在manifest中找不到表 {tableName} 的路径"); + onComplete?.Invoke(false); + return; + } + + // 加载SO + Debug.Log($"[ArtResourceManager] 按需加载SO: {tableName}"); + LoadSingleTable(soPath, (success, loadTime) => + { + if (success) + { + Debug.Log($"[ArtResourceManager] SO加载成功: {tableName}, 耗时 {loadTime:F2}ms"); + } + else + { + Debug.LogError($"[ArtResourceManager] SO加载失败: {tableName}"); + } + onComplete?.Invoke(success); + }); } /// @@ -480,15 +660,26 @@ namespace CrazyMaple /// public void LoadTableByName(string tableName, Action onComplete = null) { - if (tablesByName.TryGetValue(tableName, out ArtTableSO table)) + // 延迟加载模式:先确保SO已加载 + if (!tablesByName.TryGetValue(tableName, out ArtTableSO table)) { - LoadTable(table.TableId, onComplete); - } - else - { - Debug.LogError($"[ArtResourceManager] LoadTableByName失败: 找不到表名称 '{tableName}'"); - onComplete?.Invoke(false); + // SO还没加载,先按需加载SO + LoadTableSO(tableName, success => + { + if (success && tablesByName.TryGetValue(tableName, out table)) + { + LoadTable(table.TableId, onComplete); + } + else + { + Debug.LogError($"[ArtResourceManager] LoadTableByName失败: 无法加载表 '{tableName}'"); + onComplete?.Invoke(false); + } + }); + return; } + + LoadTable(table.TableId, onComplete); } /// @@ -532,12 +723,25 @@ namespace CrazyMaple /// public void LoadSprite(string tableName, int itemId, Action onComplete) { + // 延迟加载模式:先确保SO已加载 if (!tablesByName.TryGetValue(tableName, out ArtTableSO table)) { - Debug.LogError($"[ArtResourceManager] LoadSprite失败: 找不到表名称 '{tableName}'"); - onComplete?.Invoke(null); + // SO还没加载,先按需加载SO + LoadTableSO(tableName, success => + { + if (success && tablesByName.TryGetValue(tableName, out table)) + { + LoadSpriteInternal(table.TableId, itemId, null, onComplete); + } + else + { + Debug.LogError($"[ArtResourceManager] LoadSprite失败: 无法加载表 '{tableName}'"); + onComplete?.Invoke(null); + } + }); return; } + LoadSpriteInternal(table.TableId, itemId, null, onComplete); } @@ -546,12 +750,25 @@ namespace CrazyMaple /// public void LoadSprite(string tableName, string itemName, Action onComplete) { + // 延迟加载模式:先确保SO已加载 if (!tablesByName.TryGetValue(tableName, out ArtTableSO table)) { - Debug.LogError($"[ArtResourceManager] LoadSprite失败: 找不到表名称 '{tableName}'"); - onComplete?.Invoke(null); + // SO还没加载,先按需加载SO + LoadTableSO(tableName, success => + { + if (success && tablesByName.TryGetValue(tableName, out table)) + { + LoadSpriteInternal(table.TableId, null, itemName, onComplete); + } + else + { + Debug.LogError($"[ArtResourceManager] LoadSprite失败: 无法加载表 '{tableName}'"); + onComplete?.Invoke(null); + } + }); return; } + LoadSpriteInternal(table.TableId, null, itemName, onComplete); } @@ -654,12 +871,25 @@ namespace CrazyMaple /// public void LoadSpine(string tableName, int itemId, Action onComplete) { + // 延迟加载模式:先确保SO已加载 if (!tablesByName.TryGetValue(tableName, out ArtTableSO table)) { - Debug.LogError($"[ArtResourceManager] LoadSpine失败: 找不到表名称 '{tableName}'"); - onComplete?.Invoke(null, ""); + // SO还没加载,先按需加载SO + LoadTableSO(tableName, success => + { + if (success && tablesByName.TryGetValue(tableName, out table)) + { + LoadSpineInternal(table.TableId, itemId, null, onComplete); + } + else + { + Debug.LogError($"[ArtResourceManager] LoadSpine失败: 无法加载表 '{tableName}'"); + onComplete?.Invoke(null, ""); + } + }); return; } + LoadSpineInternal(table.TableId, itemId, null, onComplete); } @@ -668,12 +898,25 @@ namespace CrazyMaple /// public void LoadSpine(string tableName, string itemName, Action onComplete) { + // 延迟加载模式:先确保SO已加载 if (!tablesByName.TryGetValue(tableName, out ArtTableSO table)) { - Debug.LogError($"[ArtResourceManager] LoadSpine失败: 找不到表名称 '{tableName}'"); - onComplete?.Invoke(null, ""); + // SO还没加载,先按需加载SO + LoadTableSO(tableName, success => + { + if (success && tablesByName.TryGetValue(tableName, out table)) + { + LoadSpineInternal(table.TableId, null, itemName, onComplete); + } + else + { + Debug.LogError($"[ArtResourceManager] LoadSpine失败: 无法加载表 '{tableName}'"); + onComplete?.Invoke(null, ""); + } + }); return; } + LoadSpineInternal(table.TableId, null, itemName, onComplete); } @@ -881,7 +1124,7 @@ namespace CrazyMaple // Runtime模式:需要通过路径加载 if (string.IsNullOrEmpty(item.SpineAssetPath)) { - Debug.LogError($"[ArtResourceManager] Spine资源引用和路径都为空: {item.Name}"); + Debug.Log($"[ArtResourceManager] Spine资源引用和路径都为空: {item.Name}"); onComplete?.Invoke(null); return; } @@ -1191,8 +1434,12 @@ namespace CrazyMaple if (!tablesByName.TryGetValue(tableName, out ArtTableSO table)) { - Debug.LogError($"[ArtResourceManager] GetSpritePath失败: 找不到表名 {tableName}"); - return null; + // 延迟加载模式:尝试同步加载表 + if (!TrySyncLoadTable(tableName, out table)) + { + Debug.LogError($"[ArtResourceManager] GetSpritePath失败: 找不到表名 {tableName}"); + return null; + } } var item = table.Items.FirstOrDefault(x => x.Id == itemId); @@ -1227,8 +1474,12 @@ namespace CrazyMaple if (!tablesByName.TryGetValue(tableName, out ArtTableSO table)) { - Debug.LogError($"[ArtResourceManager] GetSpritePath失败: 找不到表名 {tableName}"); - return null; + // 延迟加载模式:尝试同步加载表 + if (!TrySyncLoadTable(tableName, out table)) + { + Debug.LogError($"[ArtResourceManager] GetSpritePath失败: 找不到表名 {tableName}"); + return null; + } } var item = table.Items.FirstOrDefault(x => x.Name == itemName);