美术工具移动到submodule下可以给程序使用

This commit is contained in:
zhang hongbo 2026-02-03 11:36:19 +08:00
parent 8e0c5e2b58
commit 811527ae24
15 changed files with 402 additions and 3776 deletions

View File

@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: e7a5ac633e81c834e9838be40437acec
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

File diff suppressed because it is too large Load Diff

View File

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: bb41d2b0834d59546b919fe5439e5e35
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,226 +0,0 @@
using UnityEngine;
using UnityEditor;
using ArtResource;
using System.Diagnostics;
using Debug = UnityEngine.Debug;
namespace CrazyMaple.Editor
{
/// <summary>
/// 测试工具验证SO加载时是否会连带加载引用资源
///
/// 测试方法:
/// 1. 在加载SO前后检查内存中的资源数量
/// 2. 分别测试带引用和不带引用的SO
/// 3. 分析加载耗时差异
/// </summary>
public class ArtResourceLoadTest : EditorWindow
{
[MenuItem("美术工具/性能测试工具/测试SO加载行为")]
public static void ShowWindow()
{
GetWindow<ArtResourceLoadTest>("SO加载测试");
}
private void OnGUI()
{
GUILayout.Label("SO加载行为测试", EditorStyles.boldLabel);
GUILayout.Space(10);
if (GUILayout.Button("测试1: 检查SO序列化大小", GUILayout.Height(40)))
{
TestSerializationSize();
}
GUILayout.Space(5);
if (GUILayout.Button("测试2: 对比加载时间(带引用 vs 纯路径)", GUILayout.Height(40)))
{
TestLoadingTime();
}
GUILayout.Space(5);
if (GUILayout.Button("测试3: 检查内存占用(加载前后)", GUILayout.Height(40)))
{
TestMemoryUsage();
}
GUILayout.Space(10);
EditorGUILayout.HelpBox(
"这些测试将帮助确定:\n" +
"1. SO是否会连带加载引用资源\n" +
"2. 引用字段对加载速度的影响\n" +
"3. 内存占用差异",
MessageType.Info);
}
/// <summary>
/// 测试1: 检查SO序列化后的文件大小
/// </summary>
private void TestSerializationSize()
{
Debug.Log("========== 测试1: SO序列化大小 ==========");
string[] guids = AssetDatabase.FindAssets("t:ArtTableSO");
if (guids.Length == 0)
{
Debug.LogWarning("未找到任何ArtTableSO");
return;
}
foreach (var guid in guids)
{
string path = AssetDatabase.GUIDToAssetPath(guid);
var table = AssetDatabase.LoadAssetAtPath<ArtTableSO>(path);
if (table != null)
{
// 获取文件大小
var fileInfo = new System.IO.FileInfo(path);
long fileSize = fileInfo.Length;
// 统计引用数量
int spriteRefCount = 0;
int spineRefCount = 0;
int pathCount = 0;
foreach (var item in table.Items)
{
if (item.Sprite != null) spriteRefCount++;
if (item.SpineAsset != null) spineRefCount++;
if (!string.IsNullOrEmpty(item.SpritePath) || !string.IsNullOrEmpty(item.SpineAssetPath))
pathCount++;
}
Debug.Log($"SO: {table.TableName}\n" +
$" 文件大小: {fileSize / 1024f:F2} KB\n" +
$" 资源项数: {table.Items.Count}\n" +
$" Sprite引用: {spriteRefCount}\n" +
$" Spine引用: {spineRefCount}\n" +
$" 路径字段: {pathCount}");
}
}
Debug.Log("========== 测试1 完成 ==========");
EditorUtility.DisplayDialog("测试完成", "请查看Console日志了解SO文件大小和引用情况", "确定");
}
/// <summary>
/// 测试2: 对比加载时间
/// </summary>
private void TestLoadingTime()
{
Debug.Log("========== 测试2: 加载时间对比 ==========");
string[] guids = AssetDatabase.FindAssets("t:ArtTableSO");
if (guids.Length == 0)
{
Debug.LogWarning("未找到任何ArtTableSO");
return;
}
foreach (var guid in guids)
{
string path = AssetDatabase.GUIDToAssetPath(guid);
// 卸载以确保测试准确
Resources.UnloadUnusedAssets();
System.GC.Collect();
// 测试加载时间
var sw = Stopwatch.StartNew();
var table = AssetDatabase.LoadAssetAtPath<ArtTableSO>(path);
sw.Stop();
if (table != null)
{
// 统计引用情况
int refCount = 0;
foreach (var item in table.Items)
{
if (item.Sprite != null || item.SpineAsset != null)
refCount++;
}
Debug.Log($"SO: {table.TableName}\n" +
$" 加载耗时: {sw.Elapsed.TotalMilliseconds:F2} ms\n" +
$" 资源项数: {table.Items.Count}\n" +
$" 含引用项: {refCount}\n" +
$" 平均耗时: {sw.Elapsed.TotalMilliseconds / table.Items.Count:F3} ms/项");
// 尝试访问一个引用,看看是否触发额外加载
if (table.Items.Count > 0 && table.Items[0].Sprite != null)
{
var sw2 = Stopwatch.StartNew();
var sprite = table.Items[0].Sprite; // 访问引用
var name = sprite.name; // 访问属性
sw2.Stop();
Debug.Log($" 访问第1个Sprite引用: {sw2.Elapsed.TotalMilliseconds:F2} ms");
}
}
}
Debug.Log("========== 测试2 完成 ==========");
EditorUtility.DisplayDialog("测试完成", "请查看Console日志了解加载时间差异", "确定");
}
/// <summary>
/// 测试3: 检查内存占用
/// </summary>
private void TestMemoryUsage()
{
Debug.Log("========== 测试3: 内存占用测试 ==========");
// 清理内存
Resources.UnloadUnusedAssets();
System.GC.Collect();
long memBefore = System.GC.GetTotalMemory(true);
int textureBefore = Resources.FindObjectsOfTypeAll<Texture2D>().Length;
int spriteBefore = Resources.FindObjectsOfTypeAll<Sprite>().Length;
Debug.Log($"加载前:\n" +
$" 托管内存: {memBefore / 1024f / 1024f:F2} MB\n" +
$" Texture2D数量: {textureBefore}\n" +
$" Sprite数量: {spriteBefore}");
// 加载所有SO
string[] guids = AssetDatabase.FindAssets("t:ArtTableSO");
var tables = new System.Collections.Generic.List<ArtTableSO>();
foreach (var guid in guids)
{
string path = AssetDatabase.GUIDToAssetPath(guid);
var table = AssetDatabase.LoadAssetAtPath<ArtTableSO>(path);
if (table != null)
{
tables.Add(table);
}
}
long memAfter = System.GC.GetTotalMemory(false);
int textureAfter = Resources.FindObjectsOfTypeAll<Texture2D>().Length;
int spriteAfter = Resources.FindObjectsOfTypeAll<Sprite>().Length;
Debug.Log($"加载后:\n" +
$" 托管内存: {memAfter / 1024f / 1024f:F2} MB (+{(memAfter - memBefore) / 1024f / 1024f:F2} MB)\n" +
$" Texture2D数量: {textureAfter} (+{textureAfter - textureBefore})\n" +
$" Sprite数量: {spriteAfter} (+{spriteAfter - spriteBefore})");
Debug.Log($"共加载 {tables.Count} 个SO");
Debug.Log("========== 测试3 完成 ==========");
EditorUtility.DisplayDialog(
"测试完成",
$"内存增加: {(memAfter - memBefore) / 1024f / 1024f:F2} MB\n" +
$"Texture2D增加: {textureAfter - textureBefore}\n" +
$"Sprite增加: {spriteAfter - spriteBefore}\n\n" +
$"如果纹理/Sprite数量大幅增加说明确实连带加载了引用资源",
"确定");
}
}
}

View File

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 02be3aa41decbeb488dcce0eb624b081
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,296 +0,0 @@
#if UNITY_EDITOR
using UnityEngine;
using UnityEditor;
using ArtResource;
using System.Linq;
namespace ArtTools
{
/// <summary>
/// 美术资源路径自动填充工具
///
/// 功能:
/// 1. 在保存SO时自动填充SpritePath和SpineAssetPath
/// 2. 提供手动批量更新所有SO的工具
///
/// 使用方法:
/// - 自动在ArtTableSO的OnValidate或保存时调用FillResourcePaths
/// - 手动:菜单 -> 美术工具 -> 更新所有美术资源路径
/// </summary>
public static class ArtResourcePathFiller
{
/// <summary>
/// 自动填充单个SO的资源路径
/// 应该在ArtTableSO保存时调用
/// </summary>
public static void FillResourcePaths(ArtTableSO table)
{
if (table == null || table.Items == null)
return;
bool hasChanges = false;
foreach (var item in table.Items)
{
// 填充Sprite路径
if (item.Sprite != null)
{
string spritePath = AssetDatabase.GetAssetPath(item.Sprite);
if (!string.IsNullOrEmpty(spritePath) && item.SpritePath != spritePath)
{
item.SpritePath = spritePath;
hasChanges = true;
}
}
else
{
// 引用为空时,清空路径
if (!string.IsNullOrEmpty(item.SpritePath))
{
item.SpritePath = "";
hasChanges = true;
}
}
// 填充Spine路径
if (item.SpineAsset != null)
{
string spinePath = AssetDatabase.GetAssetPath(item.SpineAsset);
if (!string.IsNullOrEmpty(spinePath) && item.SpineAssetPath != spinePath)
{
item.SpineAssetPath = spinePath;
hasChanges = true;
}
}
else
{
// 引用为空时,清空路径
if (!string.IsNullOrEmpty(item.SpineAssetPath))
{
item.SpineAssetPath = "";
hasChanges = true;
}
}
}
if (hasChanges)
{
EditorUtility.SetDirty(table);
Debug.Log($"[ArtResourcePathFiller] 已更新资源路径: {table.TableName} ({table.TableId})");
}
}
/// <summary>
/// 手动批量更新所有ArtTableSO的资源路径
/// </summary>
[MenuItem("美术工具/路径管理/更新所有美术资源路径")]
public static void UpdateAllArtTablePaths()
{
// 查找所有ArtTableSO
string[] guids = AssetDatabase.FindAssets("t:ArtTableSO");
if (guids.Length == 0)
{
Debug.LogWarning("[ArtResourcePathFiller] 未找到任何ArtTableSO文件");
return;
}
int updatedCount = 0;
int totalCount = guids.Length;
EditorUtility.DisplayProgressBar("更新美术资源路径", "正在扫描...", 0);
for (int i = 0; i < guids.Length; i++)
{
string path = AssetDatabase.GUIDToAssetPath(guids[i]);
var table = AssetDatabase.LoadAssetAtPath<ArtTableSO>(path);
if (table != null)
{
EditorUtility.DisplayProgressBar(
"更新美术资源路径",
$"处理: {table.TableName} ({i + 1}/{totalCount})",
(float)i / totalCount
);
FillResourcePaths(table);
updatedCount++;
}
}
EditorUtility.ClearProgressBar();
// 保存所有修改
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
Debug.Log($"[ArtResourcePathFiller] ✓ 批量更新完成: 处理了 {updatedCount} 个ArtTableSO");
EditorUtility.DisplayDialog(
"更新完成",
$"已更新 {updatedCount} 个美术资源表的路径信息\n\n现在可以在Runtime模式下正常加载资源了",
"确定"
);
}
/// <summary>
/// 验证所有SO的路径完整性
/// </summary>
[MenuItem("美术工具/路径管理/验证美术资源路径完整性")]
public static void ValidateAllPaths()
{
string[] guids = AssetDatabase.FindAssets("t:ArtTableSO");
if (guids.Length == 0)
{
Debug.LogWarning("[ArtResourcePathFiller] 未找到任何ArtTableSO文件");
return;
}
int missingPathCount = 0;
int totalItemCount = 0;
foreach (string guid in guids)
{
string path = AssetDatabase.GUIDToAssetPath(guid);
var table = AssetDatabase.LoadAssetAtPath<ArtTableSO>(path);
if (table == null || table.Items == null)
continue;
foreach (var item in table.Items)
{
totalItemCount++;
// 检查Sprite
if (item.Sprite != null && string.IsNullOrEmpty(item.SpritePath))
{
Debug.LogWarning($"[{table.TableName}] 资源项 '{item.Name}' 有Sprite引用但缺少路径");
missingPathCount++;
}
// 检查Spine
if (item.SpineAsset != null && string.IsNullOrEmpty(item.SpineAssetPath))
{
Debug.LogWarning($"[{table.TableName}] 资源项 '{item.Name}' 有Spine引用但缺少路径");
missingPathCount++;
}
}
}
if (missingPathCount == 0)
{
Debug.Log($"[ArtResourcePathFiller] ✓ 验证通过: 所有 {totalItemCount} 个资源项的路径都完整");
EditorUtility.DisplayDialog(
"验证通过",
$"所有 {totalItemCount} 个资源项的路径都完整\n\n可以正常使用Runtime模式",
"确定"
);
}
else
{
Debug.LogError($"[ArtResourcePathFiller] ✗ 发现 {missingPathCount} 个缺少路径的资源项");
EditorUtility.DisplayDialog(
"发现问题",
$"发现 {missingPathCount} 个缺少路径的资源项\n\n建议运行【美术工具 -> 更新所有美术资源路径】修复",
"确定"
);
}
}
}
/// <summary>
/// ArtTableSO的自定义Inspector
/// 在Inspector底部添加"更新路径"按钮
/// </summary>
[CustomEditor(typeof(ArtTableSO))]
public class ArtTableSOInspector : Editor
{
public override void OnInspectorGUI()
{
// 绘制默认Inspector
DrawDefaultInspector();
EditorGUILayout.Space(10);
EditorGUILayout.LabelField("", GUI.skin.horizontalSlider);
EditorGUILayout.Space(5);
var table = target as ArtTableSO;
if (table == null)
return;
// 统计信息
int spriteCount = table.Items.Count(item => item.Sprite != null);
int spineCount = table.Items.Count(item => item.SpineAsset != null);
int missingPathCount = table.Items.Count(item =>
(item.Sprite != null && string.IsNullOrEmpty(item.SpritePath)) ||
(item.SpineAsset != null && string.IsNullOrEmpty(item.SpineAssetPath))
);
EditorGUILayout.BeginVertical(EditorStyles.helpBox);
EditorGUILayout.LabelField("资源路径状态", EditorStyles.boldLabel);
EditorGUILayout.LabelField($"Sprite数量: {spriteCount}");
EditorGUILayout.LabelField($"Spine数量: {spineCount}");
if (missingPathCount > 0)
{
var oldColor = GUI.contentColor;
GUI.contentColor = Color.red;
EditorGUILayout.LabelField($"⚠️ 缺少路径: {missingPathCount}");
GUI.contentColor = oldColor;
}
else if (spriteCount > 0 || spineCount > 0)
{
var oldColor = GUI.contentColor;
GUI.contentColor = Color.green;
EditorGUILayout.LabelField("✓ 路径完整");
GUI.contentColor = oldColor;
}
EditorGUILayout.EndVertical();
EditorGUILayout.Space(5);
// 更新路径按钮
if (GUILayout.Button("🔄 更新此表的资源路径", GUILayout.Height(30)))
{
ArtResourcePathFiller.FillResourcePaths(table);
EditorUtility.SetDirty(table);
AssetDatabase.SaveAssets();
EditorUtility.DisplayDialog("更新完成", $"已更新 {table.TableName} 的资源路径", "确定");
}
EditorGUILayout.Space(5);
EditorGUILayout.HelpBox(
"提示保存SO时会自动更新路径手动点击按钮可强制更新",
MessageType.Info
);
}
}
/// <summary>
/// 资源保存时自动填充路径
/// </summary>
public class ArtTableSOAssetPostprocessor : AssetPostprocessor
{
static void OnPostprocessAllAssets(
string[] importedAssets,
string[] deletedAssets,
string[] movedAssets,
string[] movedFromAssetPaths)
{
foreach (string assetPath in importedAssets)
{
// 只处理ArtTableSO
if (!assetPath.EndsWith(".asset"))
continue;
var table = AssetDatabase.LoadAssetAtPath<ArtTableSO>(assetPath);
if (table != null)
{
ArtResourcePathFiller.FillResourcePaths(table);
}
}
}
}
}
#endif

View File

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: efcf042502779c34c99f685a9cdba938
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,288 +0,0 @@
// using UnityEngine;
// using UnityEditor;
// using System.IO;
// using System.Collections.Generic;
// using ArtResource;
// namespace EditorArt_Tools
// {
// /// <summary>
// /// 批量创建场景资源配置表
// /// </summary>
// public class BatchCreateSceneResources : EditorWindow
// {
// private const string SO_ROOT_PATH = "Assets/Art_SubModule/Art_SO/DecorateScene";
// private const string JSON_ROOT_PATH = "Assets/Art_SubModule/Art_Json/DecorateScene";
// private const string MANIFEST_PATH = "Assets/Art_SubModule/Art_SO/art_table_manifest.json";
// private int startIndex = 15;
// private int endIndex = 50;
// private string prefix = "Scene";
// private string suffix = "Resource";
// [MenuItem("美术工具/批量创建场景资源")]
// public static void ShowWindow()
// {
// var window = GetWindow<BatchCreateSceneResources>("批量创建场景资源");
// window.minSize = new Vector2(400, 300);
// window.Show();
// }
// private void OnGUI()
// {
// EditorGUILayout.LabelField("批量创建场景资源配置表", EditorStyles.boldLabel);
// EditorGUILayout.Space(10);
// EditorGUILayout.HelpBox(
// "将在以下路径创建配置表:\n" +
// $"SO: {SO_ROOT_PATH}\n" +
// $"JSON: {JSON_ROOT_PATH}",
// MessageType.Info);
// EditorGUILayout.Space(10);
// prefix = EditorGUILayout.TextField("前缀:", prefix);
// suffix = EditorGUILayout.TextField("后缀:", suffix);
// startIndex = EditorGUILayout.IntField("起始序号:", startIndex);
// endIndex = EditorGUILayout.IntField("结束序号:", endIndex);
// EditorGUILayout.Space(10);
// if (startIndex > endIndex)
// {
// EditorGUILayout.HelpBox("起始序号不能大于结束序号!", MessageType.Error);
// return;
// }
// int count = endIndex - startIndex + 1;
// EditorGUILayout.HelpBox($"将创建 {count} 个配置表", MessageType.Info);
// EditorGUILayout.Space(10);
// // 预览前几个文件名
// EditorGUILayout.LabelField("文件名预览:", EditorStyles.boldLabel);
// for (int i = 0; i < Mathf.Min(3, count); i++)
// {
// int index = startIndex + i;
// string fileName = $"{prefix}{index}{suffix}";
// EditorGUILayout.LabelField($" {i + 1}. {fileName}.asset / {fileName}.json");
// }
// if (count > 3)
// {
// EditorGUILayout.LabelField($" ... (共 {count} 个)");
// }
// EditorGUILayout.Space(20);
// GUI.backgroundColor = Color.green;
// if (GUILayout.Button("开始创建", GUILayout.Height(40)))
// {
// CreateResources();
// }
// GUI.backgroundColor = Color.white;
// }
// private void CreateResources()
// {
// if (startIndex > endIndex)
// {
// EditorUtility.DisplayDialog("错误", "起始序号不能大于结束序号!", "确定");
// return;
// }
// // 确保目录存在
// if (!Directory.Exists(SO_ROOT_PATH))
// {
// Directory.CreateDirectory(SO_ROOT_PATH);
// }
// if (!Directory.Exists(JSON_ROOT_PATH))
// {
// Directory.CreateDirectory(JSON_ROOT_PATH);
// }
// int successCount = 0;
// int skipCount = 0;
// List<string> createdFiles = new List<string>();
// int baseTableId = GetNextAvailableTableId();
// for (int i = startIndex; i <= endIndex; i++)
// {
// string fileName = $"{prefix}{i}{suffix}";
// string soPath = $"{SO_ROOT_PATH}/{fileName}.asset";
// string jsonPath = $"{JSON_ROOT_PATH}/{fileName}.json";
// // 检查文件是否已存在
// if (File.Exists(soPath) || File.Exists(jsonPath))
// {
// skipCount++;
// Debug.LogWarning($"文件已存在,跳过: {fileName}");
// continue;
// }
// // 创建 ScriptableObject
// var newTable = ScriptableObject.CreateInstance<ArtTableSO>();
// newTable.TableName = fileName;
// newTable.TableId = baseTableId + (i - startIndex);
// newTable.Items = new List<ArtItemData>();
// // 保存 SO 文件
// AssetDatabase.CreateAsset(newTable, soPath);
// // 创建 JSON 文件
// var jsonData = new ArtTableJsonData
// {
// TableId = newTable.TableId,
// TableName = newTable.TableName,
// Items = new List<ArtItemJsonData>()
// };
// string json = JsonUtility.ToJson(jsonData, true);
// File.WriteAllText(jsonPath, json);
// createdFiles.Add(fileName);
// successCount++;
// // 显示进度
// float progress = (float)(i - startIndex + 1) / (endIndex - startIndex + 1);
// EditorUtility.DisplayProgressBar("创建资源", $"正在创建 {fileName}...", progress);
// }
// EditorUtility.ClearProgressBar();
// // 刷新 AssetDatabase
// AssetDatabase.SaveAssets();
// AssetDatabase.Refresh();
// // 更新 Manifest
// UpdateManifest();
// // 显示结果
// string message = $"创建完成!\n成功创建: {successCount} 个\n跳过已存在: {skipCount} 个";
// if (createdFiles.Count > 0)
// {
// message += $"\n\n创建的文件:\n{string.Join("\n", createdFiles.ToArray())}";
// }
// EditorUtility.DisplayDialog("批量创建完成", message, "确定");
// Debug.Log($"[BatchCreateSceneResources] {message}");
// }
// private int GetNextAvailableTableId()
// {
// // 查找所有现有的 ArtTableSO获取最大的 TableId
// string[] guids = AssetDatabase.FindAssets("t:ArtTableSO");
// int maxId = 0;
// foreach (string guid in guids)
// {
// string path = AssetDatabase.GUIDToAssetPath(guid);
// var table = AssetDatabase.LoadAssetAtPath<ArtTableSO>(path);
// if (table != null && table.TableId > maxId)
// {
// maxId = table.TableId;
// }
// }
// return maxId + 1;
// }
// private void UpdateManifest()
// {
// try
// {
// // 查找所有ArtTableSO文件
// string[] guids = AssetDatabase.FindAssets("t:ArtTableSO", new[] { "Assets/Art_SubModule/Art_SO" });
// List<string> tablePaths = new List<string>();
// foreach (string guid in guids)
// {
// string path = AssetDatabase.GUIDToAssetPath(guid);
// if (!string.IsNullOrEmpty(path))
// {
// tablePaths.Add(path);
// }
// }
// // 排序路径
// tablePaths.Sort();
// // 创建或更新manifest
// ArtTableManifest manifest;
// // 如果文件存在,读取现有的预加载配置
// if (File.Exists(MANIFEST_PATH))
// {
// string existingJson = File.ReadAllText(MANIFEST_PATH);
// manifest = JsonUtility.FromJson<ArtTableManifest>(existingJson);
// // 确保字段不为null
// if (manifest == null)
// {
// manifest = new ArtTableManifest();
// }
// if (manifest.preloadTableIds == null)
// {
// manifest.preloadTableIds = new int[0];
// }
// }
// else
// {
// // 创建新的manifest
// manifest = new ArtTableManifest
// {
// preloadTableIds = new int[0]
// };
// }
// // 更新路径列表
// manifest.tablePaths = tablePaths.ToArray();
// // 序列化为JSON
// string json = JsonUtility.ToJson(manifest, true);
// // 确保目录存在
// string directory = Path.GetDirectoryName(MANIFEST_PATH);
// if (!Directory.Exists(directory))
// {
// Directory.CreateDirectory(directory);
// }
// // 写入文件
// File.WriteAllText(MANIFEST_PATH, json);
// AssetDatabase.ImportAsset(MANIFEST_PATH);
// Debug.Log($"[BatchCreateSceneResources] Manifest文件已更新: {MANIFEST_PATH}, 共 {tablePaths.Count} 个表");
// }
// catch (System.Exception ex)
// {
// Debug.LogError($"[BatchCreateSceneResources] 更新Manifest文件失败: {ex.Message}");
// }
// }
// [System.Serializable]
// public class ArtTableManifest
// {
// public string[] tablePaths;
// public int[] preloadTableIds;
// }
// [System.Serializable]
// public class ArtTableJsonData
// {
// public int TableId;
// public string TableName;
// public List<ArtItemJsonData> Items;
// }
// [System.Serializable]
// public class ArtItemJsonData
// {
// public int Id;
// public string Name;
// public string Desc;
// public string SpritePath;
// public string SpineAssetPath;
// public string SpineAnimName;
// }
// }
// }

View File

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 726a248ed54a61d418c78ad2dff018d3
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,499 +0,0 @@
// using UnityEngine;
// using UnityEditor;
// using System.IO;
// using System.Collections.Generic;
// using System.Linq;
// using ArtResource;
// namespace EditorArt_Tools
// {
// /// <summary>
// /// 批量导入场景Sprite资源到配置表
// /// </summary>
// public class BatchImportSceneSprites : EditorWindow
// {
// private const string SO_ROOT_PATH = "Assets/Art_SubModule/Art_SO/DecorateScene";
// private const string JSON_ROOT_PATH = "Assets/Art_SubModule/Art_Json/DecorateScene";
// private const string SPRITE_ROOT_PATH = "Assets/Art_SubModule/Art_Resource/Art_UISprites/Decorate";
// private const string MANIFEST_PATH = "Assets/Art_SubModule/Art_SO/art_table_manifest.json";
// private int startSceneIndex = 6;
// private int endSceneIndex = 50;
// private Vector2 scrollPosition;
// private List<ImportTask> importTasks = new List<ImportTask>();
// private bool isProcessing = false;
// private class ImportTask
// {
// public string SceneName;
// public string SoPath;
// public string SpriteFolderPath;
// public int SpriteCount;
// public bool FolderExists;
// public bool SoExists;
// public ImportStatus Status;
// }
// private enum ImportStatus
// {
// Pending,
// Success,
// Failed,
// Skipped
// }
// [MenuItem("美术工具/批量导入场景Sprite")]
// public static void ShowWindow()
// {
// var window = GetWindow<BatchImportSceneSprites>("批量导入场景Sprite");
// window.minSize = new Vector2(800, 600);
// window.Show();
// }
// private void OnEnable()
// {
// ScanTasks();
// }
// private void OnGUI()
// {
// EditorGUILayout.LabelField("批量导入场景Sprite资源", EditorStyles.boldLabel);
// EditorGUILayout.Space(10);
// EditorGUILayout.HelpBox(
// "此工具会自动扫描DecorateScene文件夹下的所有Scene配置表\n" +
// "并从对应的Sprite文件夹中批量导入所有sprite资源。",
// MessageType.Info);
// EditorGUILayout.Space(10);
// // 设置范围
// EditorGUILayout.BeginHorizontal();
// EditorGUI.BeginChangeCheck();
// startSceneIndex = EditorGUILayout.IntField("起始场景序号:", startSceneIndex, GUILayout.Width(200));
// endSceneIndex = EditorGUILayout.IntField("结束场景序号:", endSceneIndex, GUILayout.Width(200));
// if (EditorGUI.EndChangeCheck())
// {
// ScanTasks();
// }
// if (GUILayout.Button("刷新扫描", GUILayout.Width(100)))
// {
// ScanTasks();
// }
// EditorGUILayout.EndHorizontal();
// EditorGUILayout.Space(10);
// // 统计信息
// int validTasks = importTasks.Count(t => t.FolderExists && t.SoExists && t.SpriteCount > 0);
// int totalSprites = importTasks.Where(t => t.FolderExists && t.SoExists).Sum(t => t.SpriteCount);
// EditorGUILayout.BeginHorizontal("box");
// EditorGUILayout.LabelField($"找到配置表: {importTasks.Count(t => t.SoExists)} 个");
// EditorGUILayout.LabelField($"可导入任务: {validTasks} 个");
// EditorGUILayout.LabelField($"总Sprite数: {totalSprites} 个");
// EditorGUILayout.EndHorizontal();
// EditorGUILayout.Space(10);
// // 任务列表
// EditorGUILayout.LabelField("导入任务列表:", EditorStyles.boldLabel);
// scrollPosition = EditorGUILayout.BeginScrollView(scrollPosition);
// foreach (var task in importTasks)
// {
// DrawTaskItem(task);
// }
// EditorGUILayout.EndScrollView();
// EditorGUILayout.Space(10);
// // 操作按钮
// GUI.enabled = !isProcessing && validTasks > 0;
// GUI.backgroundColor = Color.green;
// if (GUILayout.Button("开始批量导入", GUILayout.Height(40)))
// {
// StartBatchImport();
// }
// GUI.backgroundColor = Color.white;
// GUI.enabled = true;
// if (isProcessing)
// {
// EditorGUILayout.HelpBox("正在处理中,请稍候...", MessageType.Warning);
// }
// }
// private void DrawTaskItem(ImportTask task)
// {
// Color originalBg = GUI.backgroundColor;
// // 根据状态设置背景色
// switch (task.Status)
// {
// case ImportStatus.Success:
// GUI.backgroundColor = new Color(0.5f, 1f, 0.5f, 0.3f);
// break;
// case ImportStatus.Failed:
// GUI.backgroundColor = new Color(1f, 0.5f, 0.5f, 0.3f);
// break;
// case ImportStatus.Skipped:
// GUI.backgroundColor = new Color(1f, 1f, 0.5f, 0.3f);
// break;
// }
// EditorGUILayout.BeginVertical("box");
// GUI.backgroundColor = originalBg;
// EditorGUILayout.BeginHorizontal();
// // 状态图标
// string statusIcon = task.Status switch
// {
// ImportStatus.Success => "✔",
// ImportStatus.Failed => "✘",
// ImportStatus.Skipped => "⊘",
// _ => "○"
// };
// EditorGUILayout.LabelField(statusIcon, GUILayout.Width(20));
// // 场景名称
// EditorGUILayout.LabelField(task.SceneName, EditorStyles.boldLabel, GUILayout.Width(150));
// // SO状态
// if (task.SoExists)
// {
// GUI.color = Color.green;
// EditorGUILayout.LabelField("SO✔", GUILayout.Width(40));
// }
// else
// {
// GUI.color = Color.red;
// EditorGUILayout.LabelField("SO✘", GUILayout.Width(40));
// }
// GUI.color = Color.white;
// // 文件夹状态
// if (task.FolderExists)
// {
// GUI.color = Color.green;
// EditorGUILayout.LabelField($"文件夹✔ ({task.SpriteCount} sprites)", GUILayout.Width(150));
// }
// else
// {
// GUI.color = Color.red;
// EditorGUILayout.LabelField("文件夹✘", GUILayout.Width(150));
// }
// GUI.color = Color.white;
// GUILayout.FlexibleSpace();
// // 状态文本
// if (task.Status != ImportStatus.Pending)
// {
// EditorGUILayout.LabelField(task.Status.ToString(), GUILayout.Width(80));
// }
// EditorGUILayout.EndHorizontal();
// // 路径信息
// EditorGUI.indentLevel++;
// EditorGUILayout.LabelField($"SO: {task.SoPath}", EditorStyles.miniLabel);
// EditorGUILayout.LabelField($"Sprite: {task.SpriteFolderPath}", EditorStyles.miniLabel);
// EditorGUI.indentLevel--;
// EditorGUILayout.EndVertical();
// }
// private void ScanTasks()
// {
// importTasks.Clear();
// for (int i = startSceneIndex; i <= endSceneIndex; i++)
// {
// string sceneName = $"Scene{i}Resource";
// string soPath = $"{SO_ROOT_PATH}/{sceneName}.asset";
// string spriteFolderPath = $"{SPRITE_ROOT_PATH}/Scene{i}";
// var task = new ImportTask
// {
// SceneName = sceneName,
// SoPath = soPath,
// SpriteFolderPath = spriteFolderPath,
// SoExists = File.Exists(soPath),
// FolderExists = Directory.Exists(spriteFolderPath),
// Status = ImportStatus.Pending
// };
// // 统计Sprite数量
// if (task.FolderExists)
// {
// string[] guids = AssetDatabase.FindAssets("t:Sprite", new[] { spriteFolderPath });
// task.SpriteCount = guids.Length;
// }
// importTasks.Add(task);
// }
// Repaint();
// }
// private void StartBatchImport()
// {
// isProcessing = true;
// int successCount = 0;
// int failedCount = 0;
// int skippedCount = 0;
// int totalSpritesImported = 0;
// try
// {
// for (int i = 0; i < importTasks.Count; i++)
// {
// var task = importTasks[i];
// // 跳过无效任务
// if (!task.SoExists || !task.FolderExists || task.SpriteCount == 0)
// {
// task.Status = ImportStatus.Skipped;
// skippedCount++;
// continue;
// }
// // 显示进度
// float progress = (float)i / importTasks.Count;
// EditorUtility.DisplayProgressBar("批量导入", $"正在处理 {task.SceneName}...", progress);
// // 加载SO
// var table = AssetDatabase.LoadAssetAtPath<ArtTableSO>(task.SoPath);
// if (table == null)
// {
// Debug.LogError($"无法加载配置表: {task.SoPath}");
// task.Status = ImportStatus.Failed;
// failedCount++;
// continue;
// }
// // 获取所有Sprite
// string[] guids = AssetDatabase.FindAssets("t:Sprite", new[] { task.SpriteFolderPath });
// if (guids.Length == 0)
// {
// task.Status = ImportStatus.Skipped;
// skippedCount++;
// continue;
// }
// // 获取当前最大ID
// int startId = table.Items.Count > 0 ? table.Items.Max(item => item.Id) + 1 : 1;
// // 导入Sprite
// int importedCount = 0;
// foreach (string guid in guids)
// {
// string assetPath = AssetDatabase.GUIDToAssetPath(guid);
// Sprite sprite = AssetDatabase.LoadAssetAtPath<Sprite>(assetPath);
// if (sprite != null)
// {
// // 检查是否已存在同名资源
// if (table.Items.Any(item => item.Name == sprite.name))
// {
// Debug.LogWarning($"[{task.SceneName}] 跳过重复资源: {sprite.name}");
// continue;
// }
// var newItem = new ArtItemData
// {
// Id = startId + importedCount,
// Name = sprite.name,
// Desc = "",
// Sprite = sprite
// };
// table.Items.Add(newItem);
// importedCount++;
// }
// }
// if (importedCount > 0)
// {
// // 保存SO
// EditorUtility.SetDirty(table);
// AssetDatabase.SaveAssets();
// // 同步JSON
// SyncToJson(table);
// task.Status = ImportStatus.Success;
// successCount++;
// totalSpritesImported += importedCount;
// Debug.Log($"[{task.SceneName}] 成功导入 {importedCount} 个sprite资源");
// }
// else
// {
// task.Status = ImportStatus.Skipped;
// skippedCount++;
// }
// Repaint();
// }
// // 更新Manifest
// UpdateManifest();
// }
// finally
// {
// EditorUtility.ClearProgressBar();
// isProcessing = false;
// }
// // 显示结果
// string message = $"批量导入完成!\n\n" +
// $"✔ 成功: {successCount} 个配置表\n" +
// $"✘ 失败: {failedCount} 个\n" +
// $"⊘ 跳过: {skippedCount} 个\n" +
// $"📦 总共导入: {totalSpritesImported} 个sprite";
// EditorUtility.DisplayDialog("批量导入完成", message, "确定");
// Debug.Log($"[BatchImportSceneSprites] {message}");
// Repaint();
// }
// private void SyncToJson(ArtTableSO table)
// {
// string soPath = AssetDatabase.GetAssetPath(table);
// string relativePath = soPath.Replace(SO_ROOT_PATH, "").Replace(".asset", ".json");
// string jsonPath = JSON_ROOT_PATH + relativePath;
// // 确保目录存在
// string directory = Path.GetDirectoryName(jsonPath);
// if (!Directory.Exists(directory))
// {
// Directory.CreateDirectory(directory);
// }
// // 创建JSON数据
// var jsonData = new ArtTableJsonData
// {
// TableId = table.TableId,
// TableName = table.TableName,
// Items = table.Items.Select(item => new ArtItemJsonData
// {
// Id = item.Id,
// Name = item.Name,
// Desc = item.Desc,
// SpritePath = item.Sprite != null ? AssetDatabase.GetAssetPath(item.Sprite) : "",
// SpineAssetPath = item.SpineAsset != null ? AssetDatabase.GetAssetPath(item.SpineAsset) : "",
// SpineAnimName = item.SpineAnimName
// }).ToList()
// };
// string json = JsonUtility.ToJson(jsonData, true);
// File.WriteAllText(jsonPath, json);
// AssetDatabase.ImportAsset(jsonPath);
// }
// private void UpdateManifest()
// {
// try
// {
// // 查找所有ArtTableSO文件
// string[] guids = AssetDatabase.FindAssets("t:ArtTableSO", new[] { "Assets/Art_SubModule/Art_SO" });
// List<string> tablePaths = new List<string>();
// foreach (string guid in guids)
// {
// string path = AssetDatabase.GUIDToAssetPath(guid);
// if (!string.IsNullOrEmpty(path))
// {
// tablePaths.Add(path);
// }
// }
// // 排序路径
// tablePaths.Sort();
// // 创建或更新manifest
// ArtTableManifest manifest;
// // 如果文件存在,读取现有的预加载配置
// if (File.Exists(MANIFEST_PATH))
// {
// string existingJson = File.ReadAllText(MANIFEST_PATH);
// manifest = JsonUtility.FromJson<ArtTableManifest>(existingJson);
// if (manifest == null)
// {
// manifest = new ArtTableManifest();
// }
// if (manifest.preloadTableIds == null)
// {
// manifest.preloadTableIds = new int[0];
// }
// }
// else
// {
// manifest = new ArtTableManifest
// {
// preloadTableIds = new int[0]
// };
// }
// // 更新路径列表
// manifest.tablePaths = tablePaths.ToArray();
// // 序列化为JSON
// string json = JsonUtility.ToJson(manifest, true);
// // 确保目录存在
// string directory = Path.GetDirectoryName(MANIFEST_PATH);
// if (!Directory.Exists(directory))
// {
// Directory.CreateDirectory(directory);
// }
// // 写入文件
// File.WriteAllText(MANIFEST_PATH, json);
// AssetDatabase.ImportAsset(MANIFEST_PATH);
// Debug.Log($"[BatchImportSceneSprites] Manifest文件已更新: {MANIFEST_PATH}");
// }
// catch (System.Exception ex)
// {
// Debug.LogError($"[BatchImportSceneSprites] 更新Manifest文件失败: {ex.Message}");
// }
// }
// [System.Serializable]
// public class ArtTableManifest
// {
// public string[] tablePaths;
// public int[] preloadTableIds;
// }
// [System.Serializable]
// public class ArtTableJsonData
// {
// public int TableId;
// public string TableName;
// public List<ArtItemJsonData> Items;
// }
// [System.Serializable]
// public class ArtItemJsonData
// {
// public int Id;
// public string Name;
// public string Desc;
// public string SpritePath;
// public string SpineAssetPath;
// public string SpineAnimName;
// }
// }
// }

View File

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: b80c4bb5f244fba42b19940341c9efee
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,131 +0,0 @@
using UnityEngine;
using UnityEditor;
using ArtResource;
using System.Diagnostics;
using GameFramework.Resource;
using UnityGameFramework.Runtime;
using Debug = UnityEngine.Debug;
namespace CrazyMaple.Editor
{
/// <summary>
/// 对比测试AssetDatabase vs GameEntry.Resource.LoadAsset
/// </summary>
public class LoadMethodComparisonTest : EditorWindow
{
[MenuItem("美术工具/性能测试工具/对比加载方式性能")]
public static void ShowWindow()
{
GetWindow<LoadMethodComparisonTest>("加载方式对比");
}
private void OnGUI()
{
GUILayout.Label("对比测试", EditorStyles.boldLabel);
GUILayout.Space(10);
EditorGUILayout.HelpBox(
"对比两种加载方式的性能差异:\n" +
"1. AssetDatabase.LoadAssetAtPathEditor专用\n" +
"2. GameEntry.Resource.LoadAsset框架统一接口",
MessageType.Info);
GUILayout.Space(10);
if (GUILayout.Button("运行对比测试", GUILayout.Height(40)))
{
RunComparisonTest();
}
}
private void RunComparisonTest()
{
Debug.Log("========== 加载方式性能对比 ==========");
string[] guids = AssetDatabase.FindAssets("t:ArtTableSO");
if (guids.Length == 0)
{
Debug.LogWarning("未找到任何ArtTableSO");
return;
}
// 清理缓存
Resources.UnloadUnusedAssets();
System.GC.Collect();
foreach (var guid in guids)
{
string path = AssetDatabase.GUIDToAssetPath(guid);
Debug.Log($"\n--- 测试文件: {path} ---");
// 方法1: AssetDatabaseEditor专用最直接
Resources.UnloadUnusedAssets();
var sw1 = Stopwatch.StartNew();
var table1 = AssetDatabase.LoadAssetAtPath<ArtTableSO>(path);
sw1.Stop();
Debug.Log($"[AssetDatabase] 加载耗时: {sw1.Elapsed.TotalMilliseconds:F2} ms");
// 方法2: GameEntry.Resource框架接口通过EditorResourceComponent
Resources.UnloadUnusedAssets();
// 检查 GameEntry 是否已初始化
if (GameEntry.Resource == null)
{
Debug.LogWarning("[GameEntry.Resource] GameEntry未初始化请先运行游戏或在Play模式下测试");
Debug.LogWarning("跳过GameEntry.Resource测试只显示AssetDatabase结果");
continue;
}
var sw2 = Stopwatch.StartNew();
bool loadCompleted = false;
ArtTableSO table2 = null;
var callbacks = new LoadAssetCallbacks(
(assetName, asset, duration, userData) =>
{
sw2.Stop();
table2 = asset as ArtTableSO;
loadCompleted = true;
Debug.Log($"[GameEntry.Resource] 加载耗时: {sw2.Elapsed.TotalMilliseconds:F2} ms");
Debug.Log($" - Framework报告的duration: {duration:F4} 秒 ({duration * 1000:F2} ms)");
},
(assetName, status, errorMessage, userData) =>
{
sw2.Stop();
loadCompleted = true;
Debug.LogError($"[GameEntry.Resource] 加载失败: {errorMessage}");
}
);
GameEntry.Resource.LoadAsset(path, typeof(ArtTableSO), callbacks);
// 等待异步加载完成Editor模式下实际是同步的但需要等待回调
int timeout = 0;
while (!loadCompleted && timeout < 1000)
{
System.Threading.Thread.Sleep(1);
timeout++;
}
if (!loadCompleted)
{
Debug.LogError("[GameEntry.Resource] 加载超时!");
}
// 对比
if (table1 != null && table2 != null)
{
float ratio = (float)sw2.Elapsed.TotalMilliseconds / (float)sw1.Elapsed.TotalMilliseconds;
Debug.Log($"性能差异: GameEntry.Resource 比 AssetDatabase 慢 {ratio:F1}x");
}
}
Debug.Log("\n========== 测试完成 ==========");
Debug.Log("结论: 如果GameEntry.Resource明显更慢说明EditorResourceComponent有额外开销");
Debug.Log("建议: 真机/打包后测试Runtime的AssetBundleResourceComponent性能可能完全不同");
}
}
}

View File

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 0335076a32ae570418eff3880abc9044
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,121 @@
{
"templatePinStates": [],
"dependencyTypeInfos": [
{
"userAdded": false,
"type": "UnityEngine.AnimationClip",
"defaultInstantiationMode": 0
},
{
"userAdded": false,
"type": "UnityEditor.Animations.AnimatorController",
"defaultInstantiationMode": 0
},
{
"userAdded": false,
"type": "UnityEngine.AnimatorOverrideController",
"defaultInstantiationMode": 0
},
{
"userAdded": false,
"type": "UnityEditor.Audio.AudioMixerController",
"defaultInstantiationMode": 0
},
{
"userAdded": false,
"type": "UnityEngine.ComputeShader",
"defaultInstantiationMode": 1
},
{
"userAdded": false,
"type": "UnityEngine.Cubemap",
"defaultInstantiationMode": 0
},
{
"userAdded": false,
"type": "UnityEngine.GameObject",
"defaultInstantiationMode": 0
},
{
"userAdded": false,
"type": "UnityEditor.LightingDataAsset",
"defaultInstantiationMode": 0
},
{
"userAdded": false,
"type": "UnityEngine.LightingSettings",
"defaultInstantiationMode": 0
},
{
"userAdded": false,
"type": "UnityEngine.Material",
"defaultInstantiationMode": 0
},
{
"userAdded": false,
"type": "UnityEditor.MonoScript",
"defaultInstantiationMode": 1
},
{
"userAdded": false,
"type": "UnityEngine.PhysicMaterial",
"defaultInstantiationMode": 0
},
{
"userAdded": false,
"type": "UnityEngine.PhysicsMaterial2D",
"defaultInstantiationMode": 0
},
{
"userAdded": false,
"type": "UnityEngine.Rendering.PostProcessing.PostProcessProfile",
"defaultInstantiationMode": 0
},
{
"userAdded": false,
"type": "UnityEngine.Rendering.PostProcessing.PostProcessResources",
"defaultInstantiationMode": 0
},
{
"userAdded": false,
"type": "UnityEngine.Rendering.VolumeProfile",
"defaultInstantiationMode": 0
},
{
"userAdded": false,
"type": "UnityEditor.SceneAsset",
"defaultInstantiationMode": 1
},
{
"userAdded": false,
"type": "UnityEngine.Shader",
"defaultInstantiationMode": 1
},
{
"userAdded": false,
"type": "UnityEngine.ShaderVariantCollection",
"defaultInstantiationMode": 1
},
{
"userAdded": false,
"type": "UnityEngine.Texture",
"defaultInstantiationMode": 0
},
{
"userAdded": false,
"type": "UnityEngine.Texture2D",
"defaultInstantiationMode": 0
},
{
"userAdded": false,
"type": "UnityEngine.Timeline.TimelineAsset",
"defaultInstantiationMode": 0
}
],
"defaultDependencyTypeInfo": {
"userAdded": false,
"type": "<default_scene_template_dependencies>",
"defaultInstantiationMode": 1
},
"newSceneOverride": 0
}