using System; using System.Collections.Generic; using UnityEngine; using Cysharp.Threading.Tasks; using System.Reflection; using System.Linq; #if UNITY_EDITOR using UnityEditor; #endif public class ConfigManager : ManagerBase { public bool isLoadFinished { get; private set; } private float loadingProgress = 0f; public override void Init() { base.Init(); InitConfigs(); } public virtual async UniTask InitConfigs() { // 加载配置文件 await LoadConfigs(); } protected async UniTask LoadConfigs() { loadingProgress = 0f; isLoadFinished = false; // 加载配置文件 HashSet configTypes = new HashSet() { typeof(ChestsAwardConfig), typeof(CTGConfig), typeof(DamageNumConfig), typeof(DirtyWordConfig), typeof(FaceConfig), typeof(HeroLineupHaloConfig), typeof(HeroQualityLVConfig), typeof(ItemConfig), typeof(MainChapterConfig), typeof(MainLevelConfig), typeof(NPCConfig), typeof(NPCExConfig), typeof(NPCLineupConfig), typeof(OrderInfoConfig), typeof(PlayerAttrConfig), typeof(PlayerFaceConfig), typeof(StoreConfig), typeof(SuccessConfig), typeof(SysInfoConfig), typeof(TitleStarUpConfig), typeof(TreasureSetConfig), typeof(TreeLVConfig), typeof(WindowSearchConfig), typeof(XBGetItemConfig) }; #if UNITY_EDITOR HashSet configHashSet = new HashSet(); if (System.IO.File.Exists(Application.dataPath + "/fastConfig.txt") && Launch.Instance.isOpenConfigTesting) { string[] strConfgsArr = System.IO.File.ReadAllLines(Application.dataPath + "/fastConfig.txt"); foreach (string str in strConfgsArr) { Type tpy = Type.GetType(str); configHashSet.Add(tpy); } } // 编辑器下加入 评估加载时常 foreach (var config in configHashSet) { if (!configTypes.Add(config)) { Debug.LogWarning($"配置 {config.Name} 已经存在于 configTypes 中,跳过添加。"); } } List fastName = new List(); #endif int iterator = 0; int totalConfigs = configTypes.Count; // 逐个加载配置并更新进度 foreach (var configType in configTypes) { var sw = System.Diagnostics.Stopwatch.StartNew(); LoadConfigByType(configType); sw.Stop(); #if UNITY_EDITOR if (sw.ElapsedMilliseconds >= 100) { Debug.LogError($"加载配置 {configType.Name} 耗时较长: {sw.ElapsedMilliseconds} ms"); } else if (sw.ElapsedMilliseconds <= 5) { fastName.Add(configType.Name); } Debug.Log($"加载配置: {configType.Name} 用时: {sw.ElapsedMilliseconds} ms"); #endif loadingProgress = (float)(iterator++ + 1) / totalConfigs; } #if UNITY_EDITOR if (Launch.Instance.isOpenConfigTesting) { System.IO.File.WriteAllText(Application.dataPath + "/fastConfig.txt", string.Join("\n", fastName)); //加载完后卸载 foreach (var configType in configTypes) { var methodInfo = configType.GetMethod("ForceRelease", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.FlattenHierarchy); if (methodInfo != null) { methodInfo.Invoke(null, null); } } } #endif // 加载完成后设置isLoadFinished为true loadingProgress = 1f; isLoadFinished = true; } public void LoadConfigByType(Type configType) { string configName = configType.Name; if (configName.EndsWith("Config")) { configName = configName.Substring(0, configName.Length - 6); } string[] texts = ResManager.Instance.LoadConfig(configName); if (texts != null) { string[] lines = texts; var methodInfo = configType.GetMethod("Init", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.FlattenHierarchy); if (methodInfo != null) { methodInfo.Invoke(null, new object[] { lines }); // 设置初始化标志 var isInitField = configType.GetField("isInit", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static); if (isInitField != null) { isInitField.SetValue(null, true); } Debug.Log($"加载配置: {configType.Name} 成功"); } else { Debug.LogError($"配置类 {configType.Name} 没有静态Init方法"); } } else { Debug.LogError($"找不到配置文件: {configName}"); } } private async UniTask LoadConfig() where T : class { string configName = typeof(T).Name; string[] texts = ResManager.Instance.LoadConfig(configName); if (texts != null) { string[] lines = texts; var methodInfo = typeof(T).GetMethod("Init", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static); if (methodInfo != null) { methodInfo.Invoke(null, lines); // 设置初始化标志 var isInitField = typeof(T).GetField("isInit", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static); if (isInitField != null) { isInitField.SetValue(null, true); } Debug.Log($"加载配置: {typeof(T).Name} 成功"); } else { Debug.LogError($"配置类 {typeof(T).Name} 没有静态Init方法"); } } else { Debug.LogError($"找不到配置文件: {configName}"); } } public float GetLoadingProgress() { return loadingProgress; } private void ClearConfigDictionary() where T : class { // 重置 T 初始化状态 var isInitField = typeof(T).GetField("isInit", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static); if (isInitField != null) { isInitField.SetValue(null, false); } } public override void Release() { // 清空 ChestsAwardConfig 字典 ClearConfigDictionary(); // 清空 CTGConfig 字典 ClearConfigDictionary(); // 清空 DamageNumConfig 字典 ClearConfigDictionary(); // 清空 DirtyWordConfig 字典 ClearConfigDictionary(); // 清空 FaceConfig 字典 ClearConfigDictionary(); // 清空 HeroLineupHaloConfig 字典 ClearConfigDictionary(); // 清空 HeroQualityLVConfig 字典 ClearConfigDictionary(); // 清空 ItemConfig 字典 ClearConfigDictionary(); // 清空 MainChapterConfig 字典 ClearConfigDictionary(); // 清空 MainLevelConfig 字典 ClearConfigDictionary(); // 清空 NPCConfig 字典 ClearConfigDictionary(); // 清空 NPCExConfig 字典 ClearConfigDictionary(); // 清空 NPCLineupConfig 字典 ClearConfigDictionary(); // 清空 OrderInfoConfig 字典 ClearConfigDictionary(); // 清空 PlayerAttrConfig 字典 ClearConfigDictionary(); // 清空 PlayerFaceConfig 字典 ClearConfigDictionary(); // 清空 StoreConfig 字典 ClearConfigDictionary(); // 清空 SuccessConfig 字典 ClearConfigDictionary(); // 清空 SysInfoConfig 字典 ClearConfigDictionary(); // 清空 TitleStarUpConfig 字典 ClearConfigDictionary(); // 清空 TreasureSetConfig 字典 ClearConfigDictionary(); // 清空 TreeLVConfig 字典 ClearConfigDictionary(); // 清空 WindowSearchConfig 字典 ClearConfigDictionary(); // 清空 XBGetItemConfig 字典 ClearConfigDictionary(); } #if UNITY_EDITOR [MenuItem("Tools/Config/自检")] public static void CheckAndGenerateFastConfig() { // 获取 Editor Assembly var editorAsm = System.AppDomain.CurrentDomain.GetAssemblies() .FirstOrDefault(a => a.FullName.Contains("Editor")); if (editorAsm == null) { Debug.LogError("[自检] 未找到 Editor Assembly,无法自检。"); return; } // 反射获取 ConfigGenerater 类型 var configGeneraterType = editorAsm.GetType("ConfigGenerater"); if (configGeneraterType == null) { Debug.LogError("[自检] 未找到 ConfigGenerater 类型。"); return; } // 调用 GetAllConfigClasses 静态方法 var getAllConfigClassesMethod = configGeneraterType.GetMethod("GetAllConfigClasses", BindingFlags.Public | BindingFlags.Static); var allConfigClasses = getAllConfigClassesMethod?.Invoke(null, null) as List; if (allConfigClasses == null) { Debug.LogError("[自检] 获取全部配置类失败。"); return; } // 获取 ExcludeClassList 字段 var excludeField = configGeneraterType.GetField("ExcludeClassList", BindingFlags.Public | BindingFlags.Static); var excludeClassList = excludeField?.GetValue(null) as List ?? new List(); // 排除不需要的类 var checkClasses = allConfigClasses.Where(c => !excludeClassList.Contains(c)).ToList(); List fastName = new List(); foreach (var className in checkClasses) { // 这里也要用 Editor Assembly 获取类型 var configType = editorAsm.GetType(className) ?? Type.GetType(className); if (configType == null) { Debug.LogWarning($"[自检] 未找到类型: {className}"); continue; } var sw = System.Diagnostics.Stopwatch.StartNew(); // 反射调用静态Init方法 string configName = configType.Name; if (configName.EndsWith("Config")) configName = configName.Substring(0, configName.Length - 6); string[] texts = ResManager.Instance.LoadConfig(configName); if (texts != null) { string[] lines = texts; var methodInfo = configType.GetMethod("Init", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.FlattenHierarchy); if (methodInfo != null) { methodInfo.Invoke(null, new object[] { lines }); } } sw.Stop(); if (sw.ElapsedMilliseconds >= 100) { Debug.LogError($"[自检] 加载配置 {configType.Name} 耗时较长: {sw.ElapsedMilliseconds} ms"); } else if (sw.ElapsedMilliseconds <= 5) { fastName.Add(configType.Name); } Debug.Log($"[自检] 加载配置: {configType.Name} 用时: {sw.ElapsedMilliseconds} ms"); } // 释放所有已加载的配置 foreach (var className in checkClasses) { var configType = editorAsm.GetType(className) ?? Type.GetType(className); if (configType == null) continue; var methodInfo = configType.GetMethod("ForceRelease", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.FlattenHierarchy); if (methodInfo != null) { methodInfo.Invoke(null, null); } } System.IO.File.WriteAllText(Application.dataPath + "/fastConfig.txt", string.Join("\n", fastName)); Debug.Log($"[自检] fastConfig.txt 生成完毕,快速表有:{string.Join(", ", fastName)}"); } #endif }