using System; using System.Collections.Generic; using UnityEditor; using UnityEngine; namespace BaseGames.Editor { /// /// 一键应用/校验项目推荐的 Script Execution Order。 /// public static class ScriptExecutionOrderTools { private readonly struct OrderRule { public readonly string ClassName; public readonly int Order; public OrderRule(string className, int order) { ClassName = className; Order = order; } } private static readonly OrderRule[] Rules = { new OrderRule("GameServiceRegistrar", -2000), new OrderRule("GameManager", -1000), new OrderRule("SceneService", -900), new OrderRule("SaveManager", -900), new OrderRule("AudioManager", -500), new OrderRule("PlayerController", -100), }; [MenuItem("BaseGames/Tools/Apply Script Execution Order Preset")] public static void ApplyPreset() { int updated = 0; int skipped = 0; var issues = new List(); foreach (var rule in Rules) { if (!TryFindMonoScript(rule.ClassName, out MonoScript script, out string issue)) { skipped++; issues.Add(issue); continue; } int current = MonoImporter.GetExecutionOrder(script); if (current == rule.Order) continue; MonoImporter.SetExecutionOrder(script, rule.Order); updated++; } AssetDatabase.SaveAssets(); if (issues.Count > 0) { Debug.LogWarning( "[ScriptExecutionOrderTools] 已应用执行顺序预设(部分脚本未处理)。\n" + $"更新: {updated}, 跳过: {skipped}\n- {string.Join("\n- ", issues)}"); return; } Debug.Log($"[ScriptExecutionOrderTools] 执行顺序预设应用完成。更新数量: {updated}。"); } [MenuItem("BaseGames/Tools/Validate Script Execution Order Preset")] public static void ValidatePreset() { var mismatches = new List(); var issues = new List(); foreach (var rule in Rules) { if (!TryFindMonoScript(rule.ClassName, out MonoScript script, out string issue)) { issues.Add(issue); continue; } int current = MonoImporter.GetExecutionOrder(script); if (current != rule.Order) mismatches.Add($"{rule.ClassName}: 当前 {current}, 期望 {rule.Order}"); } if (mismatches.Count == 0 && issues.Count == 0) { Debug.Log("[ScriptExecutionOrderTools] 执行顺序校验通过,所有脚本均符合预设。"); return; } string message = "[ScriptExecutionOrderTools] 执行顺序校验发现问题。"; if (mismatches.Count > 0) message += "\n顺序不一致:\n- " + string.Join("\n- ", mismatches); if (issues.Count > 0) message += "\n脚本解析问题:\n- " + string.Join("\n- ", issues); Debug.LogWarning(message); } private static bool TryFindMonoScript(string className, out MonoScript script, out string issue) { script = null; issue = null; string[] guids = AssetDatabase.FindAssets($"{className} t:MonoScript"); var matches = new List(); foreach (string guid in guids) { string path = AssetDatabase.GUIDToAssetPath(guid); var candidate = AssetDatabase.LoadAssetAtPath(path); if (candidate == null) continue; Type type = candidate.GetClass(); if (type != null && type.Name == className) matches.Add(candidate); } if (matches.Count == 0) { issue = $"未找到脚本: {className}"; return false; } if (matches.Count > 1) { issue = $"存在多个同名脚本: {className}(请消歧后重试)"; return false; } script = matches[0]; return true; } } }