using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using UnityEditor; using UnityEngine; /// /// 配置生成器 - 用于自动生成配置管理器代码 /// public static class ConfigGenerater { // 常量定义 private const string ConfigsPath = "Assets/Scripts/Main/Config/Configs"; private const string ConfigManagerPath = "Assets/Scripts/Main/Config/ConfigManager.cs"; public static List ExcludeClassList = new List() { // 特殊表格 "InitialFunctionConfig", "PriorLanguageConfig", // 暂时无用的表 "PlayerFacePicStarConfig", "PlayerFaceStarConfig", }; [MenuItem("Tools/手动刷新")] public static void Refresh() { AssetDatabase.Refresh(); } /// /// 生成配置管理器菜单项 /// [MenuItem("Tools/生成配置管理器")] public static void Generate() { try { // 获取所有配置类 List configClasses = GetAllConfigClasses(); if (System.IO.File.Exists(Path.Combine(Application.dataPath, "fastConfig.txt"))) { // 如果存在 fastConfig.txt 文件,读取其中的配置类 string[] fastConfigs = System.IO.File.ReadAllLines(Path.Combine(Application.dataPath, "fastConfig.txt")); ExcludeClassList.AddRange(fastConfigs); } configClasses = new List(configClasses.Where(config => !ExcludeClassList.Contains(config))); // 生成配置管理器代码 GenerateConfigManager(configClasses); Debug.Log($"配置管理器生成完成,共找到 {configClasses.Count} 个配置类: {string.Join(", ", configClasses)}"); // 刷新资源 AssetDatabase.Refresh(); } catch (Exception ex) { Debug.LogError($"生成配置管理器时发生错误: {ex.Message}\n{ex.StackTrace}"); } } /// /// 获取所有配置类 /// /// 配置类名称列表 public static List GetAllConfigClasses() { // 获取配置目录的完整路径 string fullConfigsPath = Path.Combine(Application.dataPath, ConfigsPath.Replace("Assets/", "")); // 检查目录是否存在 if (!Directory.Exists(fullConfigsPath)) { Debug.LogError($"配置目录不存在: {fullConfigsPath}"); return new List(); } try { List configClasses = new List(); // 获取所有C#文件 string[] files = Directory.GetFiles(fullConfigsPath, "*.cs", SearchOption.TopDirectoryOnly); for (int i = 0; i < files.Length; i++) { string file = files[i]; configClasses.Add(Path.GetFileNameWithoutExtension(file)); } return configClasses; } catch (Exception ex) { Debug.LogError($"扫描配置类时发生错误: {ex.Message}"); return new List(); } } /// /// 生成配置管理器代码 /// /// 配置类列表 private static void GenerateConfigManager(List configClasses) { // 获取配置管理器的完整路径 string fullConfigManagerPath = Path.Combine(Application.dataPath, ConfigManagerPath.Replace("Assets/", "")); try { // 生成完整的配置管理器代码 string configManagerCode = GenerateFullConfigManagerCode(configClasses); // 写入文件 File.WriteAllText(fullConfigManagerPath, configManagerCode); Debug.Log($"成功生成配置管理器: {fullConfigManagerPath}"); } catch (Exception ex) { Debug.LogError($"生成配置管理器文件时发生错误: {ex.Message}"); } } /// /// 生成完整的配置管理器代码 /// /// 配置类列表 /// 完整的配置管理器代码 private static string GenerateFullConfigManagerCode(List configClasses) { StringBuilder sb = new StringBuilder(); // 头部命名空间 sb.AppendLine("using System;"); sb.AppendLine("using System.Collections.Generic;"); sb.AppendLine("using UnityEngine;"); sb.AppendLine("using Cysharp.Threading.Tasks;"); sb.AppendLine("using System.Reflection;"); sb.AppendLine("using System.Linq;"); sb.AppendLine(); sb.AppendLine("#if UNITY_EDITOR"); sb.AppendLine("using UnityEditor;"); sb.AppendLine("#endif"); sb.AppendLine(); sb.AppendLine("public class ConfigManager : ManagerBase"); sb.AppendLine("{"); sb.AppendLine(" public bool isLoadFinished"); sb.AppendLine(" {"); sb.AppendLine(" get;"); sb.AppendLine(" private set;"); sb.AppendLine(" }"); sb.AppendLine(); sb.AppendLine(" private float loadingProgress = 0f;"); sb.AppendLine(); sb.AppendLine(" public override void Init()"); sb.AppendLine(" {"); sb.AppendLine(" base.Init();"); sb.AppendLine(" InitConfigs();"); sb.AppendLine(" }"); sb.AppendLine(); sb.AppendLine(" public virtual async UniTask InitConfigs()"); sb.AppendLine(" {"); sb.AppendLine(" // 加载配置文件"); sb.AppendLine(" await LoadConfigs();"); sb.AppendLine(" }"); sb.AppendLine(); sb.AppendLine(" protected async UniTask LoadConfigs()"); sb.AppendLine(" {"); sb.AppendLine(" loadingProgress = 0f;"); sb.AppendLine(" isLoadFinished = false;"); sb.AppendLine(); sb.AppendLine(" // 加载配置文件"); sb.AppendLine(" HashSet configTypes = new HashSet() {"); for (int i = 0; i < configClasses.Count; i++) { sb.Append($" typeof({configClasses[i]})"); sb.AppendLine(i < configClasses.Count - 1 ? "," : ""); } sb.AppendLine(" };"); sb.AppendLine(); sb.AppendLine("#if UNITY_EDITOR"); sb.AppendLine(" HashSet configHashSet = new HashSet();"); sb.AppendLine(" if (System.IO.File.Exists(Application.dataPath + \"/fastConfig.txt\") && Launch.Instance.isOpenConfigTesting)"); sb.AppendLine(" {"); sb.AppendLine(" string[] strConfgsArr = System.IO.File.ReadAllLines(Application.dataPath + \"/fastConfig.txt\");"); sb.AppendLine(" foreach (string str in strConfgsArr)"); sb.AppendLine(" {"); sb.AppendLine(" Type tpy = Type.GetType(str);"); sb.AppendLine(" configHashSet.Add(tpy);"); sb.AppendLine(" }"); sb.AppendLine(" }"); sb.AppendLine(" // 编辑器下加入 评估加载时常"); sb.AppendLine(" foreach (var config in configHashSet)"); sb.AppendLine(" {"); sb.AppendLine(" if (!configTypes.Add(config))"); sb.AppendLine(" {"); sb.AppendLine(" Debug.LogWarning($\"配置 {config.Name} 已经存在于 configTypes 中,跳过添加。\");"); sb.AppendLine(" }"); sb.AppendLine(" }"); sb.AppendLine(" List fastName = new List();"); sb.AppendLine("#endif"); sb.AppendLine(" int iterator = 0;"); sb.AppendLine(" int totalConfigs = configTypes.Count;"); sb.AppendLine(); sb.AppendLine(" // 逐个加载配置并更新进度"); sb.AppendLine(" foreach (var configType in configTypes)"); sb.AppendLine(" {"); sb.AppendLine(" var sw = System.Diagnostics.Stopwatch.StartNew();"); sb.AppendLine(" LoadConfigByType(configType);"); sb.AppendLine(" sw.Stop();"); sb.AppendLine("#if UNITY_EDITOR"); sb.AppendLine(" if (sw.ElapsedMilliseconds >= 100)"); sb.AppendLine(" {"); sb.AppendLine(" Debug.LogError($\"加载配置 {configType.Name} 耗时较长: {sw.ElapsedMilliseconds} ms\");"); sb.AppendLine(" }"); sb.AppendLine(" else if (sw.ElapsedMilliseconds <= 5)"); sb.AppendLine(" {"); sb.AppendLine(" fastName.Add(configType.Name);"); sb.AppendLine(" }"); sb.AppendLine(" Debug.Log($\"加载配置: {configType.Name} 用时: {sw.ElapsedMilliseconds} ms\");"); sb.AppendLine("#endif"); sb.AppendLine(" loadingProgress = (float)(iterator++ + 1) / totalConfigs;"); sb.AppendLine(" }"); sb.AppendLine("#if UNITY_EDITOR"); sb.AppendLine(" if (Launch.Instance.isOpenConfigTesting)"); sb.AppendLine(" {"); sb.AppendLine(" System.IO.File.WriteAllText(Application.dataPath + \"/fastConfig.txt\", string.Join(\"\\n\", fastName));"); sb.AppendLine(); sb.AppendLine(" //加载完后卸载"); sb.AppendLine(" foreach (var configType in configTypes)"); sb.AppendLine(" {"); sb.AppendLine(" var methodInfo = configType.GetMethod(\"ForceRelease\", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.FlattenHierarchy);"); sb.AppendLine(" if (methodInfo != null)"); sb.AppendLine(" {"); sb.AppendLine(" methodInfo.Invoke(null, null);"); sb.AppendLine(" }"); sb.AppendLine(" }"); sb.AppendLine(" }"); sb.AppendLine("#endif"); sb.AppendLine(); sb.AppendLine(" // 加载完成后设置isLoadFinished为true"); sb.AppendLine(" loadingProgress = 1f;"); sb.AppendLine(" isLoadFinished = true;"); sb.AppendLine(" }"); sb.AppendLine(); sb.AppendLine(" public void LoadConfigByType(Type configType)"); sb.AppendLine(" {"); sb.AppendLine(" string configName = configType.Name;"); sb.AppendLine(" if (configName.EndsWith(\"Config\"))"); sb.AppendLine(" {"); sb.AppendLine(" configName = configName.Substring(0, configName.Length - 6);"); sb.AppendLine(" }"); sb.AppendLine(" string[] texts = ResManager.Instance.LoadConfig(configName);"); sb.AppendLine(" if (texts != null)"); sb.AppendLine(" {"); sb.AppendLine(" string[] lines = texts;"); sb.AppendLine(" var methodInfo = configType.GetMethod(\"Init\", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.FlattenHierarchy);"); sb.AppendLine(" if (methodInfo != null)"); sb.AppendLine(" {"); sb.AppendLine(" methodInfo.Invoke(null, new object[] { lines });"); sb.AppendLine(" // 设置初始化标志"); sb.AppendLine(" var isInitField = configType.GetField(\"isInit\", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static);"); sb.AppendLine(" if (isInitField != null)"); sb.AppendLine(" {"); sb.AppendLine(" isInitField.SetValue(null, true);"); sb.AppendLine(" }"); sb.AppendLine(" Debug.Log($\"加载配置: {configType.Name} 成功\");"); sb.AppendLine(" }"); sb.AppendLine(" else"); sb.AppendLine(" {"); sb.AppendLine(" Debug.LogError($\"配置类 {configType.Name} 没有静态Init方法\");"); sb.AppendLine(" }"); sb.AppendLine(" }"); sb.AppendLine(" else"); sb.AppendLine(" {"); sb.AppendLine(" Debug.LogError($\"找不到配置文件: {configName}\");"); sb.AppendLine(" }"); sb.AppendLine(" }"); sb.AppendLine(); sb.AppendLine(" private async UniTask LoadConfig() where T : class"); sb.AppendLine(" {"); sb.AppendLine(" string configName = typeof(T).Name;"); sb.AppendLine(); sb.AppendLine(" string[] texts = ResManager.Instance.LoadConfig(configName);"); sb.AppendLine(" if (texts != null)"); sb.AppendLine(" {"); sb.AppendLine(" string[] lines = texts;"); sb.AppendLine(" var methodInfo = typeof(T).GetMethod(\"Init\", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static);"); sb.AppendLine(" if (methodInfo != null)"); sb.AppendLine(" {"); sb.AppendLine(" methodInfo.Invoke(null, lines);"); sb.AppendLine(" // 设置初始化标志"); sb.AppendLine(" var isInitField = typeof(T).GetField(\"isInit\", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static);"); sb.AppendLine(" if (isInitField != null)"); sb.AppendLine(" {"); sb.AppendLine(" isInitField.SetValue(null, true);"); sb.AppendLine(" }"); sb.AppendLine(" Debug.Log($\"加载配置: {typeof(T).Name} 成功\");"); sb.AppendLine(" }"); sb.AppendLine(" else"); sb.AppendLine(" {"); sb.AppendLine(" Debug.LogError($\"配置类 {typeof(T).Name} 没有静态Init方法\");"); sb.AppendLine(" }"); sb.AppendLine(" }"); sb.AppendLine(" else"); sb.AppendLine(" {"); sb.AppendLine(" Debug.LogError($\"找不到配置文件: {configName}\");"); sb.AppendLine(" }"); sb.AppendLine(" }"); sb.AppendLine(); sb.AppendLine(" public float GetLoadingProgress()"); sb.AppendLine(" {"); sb.AppendLine(" return loadingProgress;"); sb.AppendLine(" }"); sb.AppendLine(); sb.AppendLine(" private void ClearConfigDictionary() where T : class"); sb.AppendLine(" {"); sb.AppendLine(" // 重置 T 初始化状态"); sb.AppendLine(" var isInitField = typeof(T).GetField(\"isInit\", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static);"); sb.AppendLine(" if (isInitField != null)"); sb.AppendLine(" {"); sb.AppendLine(" isInitField.SetValue(null, false);"); sb.AppendLine(" }"); sb.AppendLine(" }"); sb.AppendLine(); sb.AppendLine(" public override void Release()"); sb.AppendLine(" {"); foreach (string className in configClasses) { sb.AppendLine($" // 清空 {className} 字典"); sb.AppendLine($" ClearConfigDictionary<{className}>();"); } sb.AppendLine(" }"); sb.AppendLine(); sb.AppendLine("#if UNITY_EDITOR"); sb.AppendLine(" [MenuItem(\"Tools/Config/自检\")]"); sb.AppendLine(" public static void CheckAndGenerateFastConfig()"); sb.AppendLine(" {"); sb.AppendLine(" // 获取 Editor Assembly"); sb.AppendLine(" var editorAsm = System.AppDomain.CurrentDomain.GetAssemblies()"); sb.AppendLine(" .FirstOrDefault(a => a.FullName.Contains(\"Editor\"));"); sb.AppendLine(); sb.AppendLine(" if (editorAsm == null)"); sb.AppendLine(" {"); sb.AppendLine(" Debug.LogError(\"[自检] 未找到 Editor Assembly,无法自检。\");"); sb.AppendLine(" return;"); sb.AppendLine(" }"); sb.AppendLine(); sb.AppendLine(" // 反射获取 ConfigGenerater 类型"); sb.AppendLine(" var configGeneraterType = editorAsm.GetType(\"ConfigGenerater\");"); sb.AppendLine(" if (configGeneraterType == null)"); sb.AppendLine(" {"); sb.AppendLine(" Debug.LogError(\"[自检] 未找到 ConfigGenerater 类型。\");"); sb.AppendLine(" return;"); sb.AppendLine(" }"); sb.AppendLine(); sb.AppendLine(" // 调用 GetAllConfigClasses 静态方法"); sb.AppendLine(" var getAllConfigClassesMethod = configGeneraterType.GetMethod(\"GetAllConfigClasses\", BindingFlags.Public | BindingFlags.Static);"); sb.AppendLine(" var allConfigClasses = getAllConfigClassesMethod?.Invoke(null, null) as List;"); sb.AppendLine(" if (allConfigClasses == null)"); sb.AppendLine(" {"); sb.AppendLine(" Debug.LogError(\"[自检] 获取全部配置类失败。\");"); sb.AppendLine(" return;"); sb.AppendLine(" }"); sb.AppendLine(); sb.AppendLine(" // 获取 ExcludeClassList 字段"); sb.AppendLine(" var excludeField = configGeneraterType.GetField(\"ExcludeClassList\", BindingFlags.Public | BindingFlags.Static);"); sb.AppendLine(" var excludeClassList = excludeField?.GetValue(null) as List ?? new List();"); sb.AppendLine(); sb.AppendLine(" // 排除不需要的类"); sb.AppendLine(" var checkClasses = allConfigClasses.Where(c => !excludeClassList.Contains(c)).ToList();"); sb.AppendLine(); sb.AppendLine(" List fastName = new List();"); sb.AppendLine(); sb.AppendLine(" foreach (var className in checkClasses)"); sb.AppendLine(" {"); sb.AppendLine(" // 这里也要用 Editor Assembly 获取类型"); sb.AppendLine(" var configType = editorAsm.GetType(className) ?? Type.GetType(className);"); sb.AppendLine(" if (configType == null)"); sb.AppendLine(" {"); sb.AppendLine(" Debug.LogWarning($\"[自检] 未找到类型: {className}\");"); sb.AppendLine(" continue;"); sb.AppendLine(" }"); sb.AppendLine(); sb.AppendLine(" var sw = System.Diagnostics.Stopwatch.StartNew();"); sb.AppendLine(); sb.AppendLine(" // 反射调用静态Init方法"); sb.AppendLine(" string configName = configType.Name;"); sb.AppendLine(" if (configName.EndsWith(\"Config\"))"); sb.AppendLine(" configName = configName.Substring(0, configName.Length - 6);"); sb.AppendLine(); sb.AppendLine(" string[] texts = ResManager.Instance.LoadConfig(configName);"); sb.AppendLine(" if (texts != null)"); sb.AppendLine(" {"); sb.AppendLine(" string[] lines = texts;"); sb.AppendLine(" var methodInfo = configType.GetMethod(\"Init\", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.FlattenHierarchy);"); sb.AppendLine(" if (methodInfo != null)"); sb.AppendLine(" {"); sb.AppendLine(" methodInfo.Invoke(null, new object[] { lines });"); sb.AppendLine(" }"); sb.AppendLine(" }"); sb.AppendLine(); sb.AppendLine(" sw.Stop();"); sb.AppendLine(); sb.AppendLine(" if (sw.ElapsedMilliseconds >= 100)"); sb.AppendLine(" {"); sb.AppendLine(" Debug.LogError($\"[自检] 加载配置 {configType.Name} 耗时较长: {sw.ElapsedMilliseconds} ms\");"); sb.AppendLine(" }"); sb.AppendLine(" else if (sw.ElapsedMilliseconds <= 5)"); sb.AppendLine(" {"); sb.AppendLine(" fastName.Add(configType.Name);"); sb.AppendLine(" }"); sb.AppendLine(" Debug.Log($\"[自检] 加载配置: {configType.Name} 用时: {sw.ElapsedMilliseconds} ms\");"); sb.AppendLine(" }"); sb.AppendLine(); sb.AppendLine(" // 释放所有已加载的配置"); sb.AppendLine(" foreach (var className in checkClasses)"); sb.AppendLine(" {"); sb.AppendLine(" var configType = editorAsm.GetType(className) ?? Type.GetType(className);"); sb.AppendLine(" if (configType == null) continue;"); sb.AppendLine(" var methodInfo = configType.GetMethod(\"ForceRelease\", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.FlattenHierarchy);"); sb.AppendLine(" if (methodInfo != null)"); sb.AppendLine(" {"); sb.AppendLine(" methodInfo.Invoke(null, null);"); sb.AppendLine(" }"); sb.AppendLine(" }"); sb.AppendLine(); sb.AppendLine(" System.IO.File.WriteAllText(Application.dataPath + \"/fastConfig.txt\", string.Join(\"\\n\", fastName));"); sb.AppendLine(" Debug.Log($\"[自检] fastConfig.txt 生成完毕,快速表有:{string.Join(\", \", fastName)}\");"); sb.AppendLine(" }"); sb.AppendLine("#endif"); sb.AppendLine("}"); return sb.ToString(); } }