diff --git a/SkillsForUnity/Editor/Skills/SkillRouter.cs b/SkillsForUnity/Editor/Skills/SkillRouter.cs index 23950843..f1bc2bbd 100644 --- a/SkillsForUnity/Editor/Skills/SkillRouter.cs +++ b/SkillsForUnity/Editor/Skills/SkillRouter.cs @@ -3,6 +3,7 @@ using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; +using UnityEditor; using UnityEngine; using Newtonsoft.Json; using Newtonsoft.Json.Linq; @@ -340,54 +341,54 @@ public static void Initialize() var skills = new Dictionary(StringComparer.OrdinalIgnoreCase); var trackedSkills = new HashSet(StringComparer.OrdinalIgnoreCase); - var allTypes = SkillsCommon.GetAllLoadedTypes(); - - foreach (var type in allTypes) + // 使用 Unity 编辑器索引直接查询 Skill 方法,避免在 Domain Reload 后枚举全部程序集和类型。 + var methods = TypeCache.GetMethodsWithAttribute(); + foreach (var method in methods) { - foreach (var method in type.GetMethods(BindingFlags.Public | BindingFlags.Static)) + if (!method.IsPublic || !method.IsStatic) + continue; + + UnitySkillAttribute attr; + try { attr = method.GetCustomAttribute(); } + catch { continue; } + if (attr != null) { - UnitySkillAttribute attr; - try { attr = method.GetCustomAttribute(); } - catch { continue; } - if (attr != null) + var name = attr.Name ?? ToSnakeCase(method.Name); + var parameters = method.GetParameters(); + var parameterNames = parameters.Select(p => p.Name).ToArray(); + var allowedSet = new HashSet(parameterNames, StringComparer.OrdinalIgnoreCase); + allowedSet.UnionWith(_reservedBodyParameters); + if (!allowedSet.Contains(EntityIdParameterName) && SupportsSyntheticEntityId(parameterNames)) + allowedSet.Add(EntityIdParameterName); + skills[name] = new SkillInfo { - var name = attr.Name ?? ToSnakeCase(method.Name); - var parameters = method.GetParameters(); - var parameterNames = parameters.Select(p => p.Name).ToArray(); - var allowedSet = new HashSet(parameterNames, StringComparer.OrdinalIgnoreCase); - allowedSet.UnionWith(_reservedBodyParameters); - if (!allowedSet.Contains(EntityIdParameterName) && SupportsSyntheticEntityId(parameterNames)) - allowedSet.Add(EntityIdParameterName); - skills[name] = new SkillInfo - { - Name = name, - Description = attr.Description ?? "", - Method = method, - Parameters = parameters, - TracksWorkflow = attr.TracksWorkflow, - Category = attr.Category, - Operation = attr.Operation, - Tags = attr.Tags, - Outputs = attr.Outputs, - RequiresInput = attr.RequiresInput, - ReadOnly = attr.ReadOnly, - MutatesScene = attr.MutatesScene, - MutatesAssets = attr.MutatesAssets, - MayTriggerReload = attr.MayTriggerReload, - MayEnterPlayMode = attr.MayEnterPlayMode, - SupportsDryRun = attr.SupportsDryRun, - RiskLevel = attr.RiskLevel ?? "low", - RequiresPackages = attr.RequiresPackages, - Mode = attr.Mode, - ParameterNames = parameterNames, - AllowedParameterSet = allowedSet, - NameLower = name.ToLowerInvariant(), - DescriptionLower = (attr.Description ?? "").ToLowerInvariant(), - TagsLower = attr.Tags?.Select(t => t.ToLowerInvariant()).ToArray() - }; - if (attr.TracksWorkflow) - trackedSkills.Add(name); - } + Name = name, + Description = attr.Description ?? "", + Method = method, + Parameters = parameters, + TracksWorkflow = attr.TracksWorkflow, + Category = attr.Category, + Operation = attr.Operation, + Tags = attr.Tags, + Outputs = attr.Outputs, + RequiresInput = attr.RequiresInput, + ReadOnly = attr.ReadOnly, + MutatesScene = attr.MutatesScene, + MutatesAssets = attr.MutatesAssets, + MayTriggerReload = attr.MayTriggerReload, + MayEnterPlayMode = attr.MayEnterPlayMode, + SupportsDryRun = attr.SupportsDryRun, + RiskLevel = attr.RiskLevel ?? "low", + RequiresPackages = attr.RequiresPackages, + Mode = attr.Mode, + ParameterNames = parameterNames, + AllowedParameterSet = allowedSet, + NameLower = name.ToLowerInvariant(), + DescriptionLower = (attr.Description ?? "").ToLowerInvariant(), + TagsLower = attr.Tags?.Select(t => t.ToLowerInvariant()).ToArray() + }; + if (attr.TracksWorkflow) + trackedSkills.Add(name); } } diff --git a/SkillsForUnity/Editor/UI/UnitySkillsWindow.cs b/SkillsForUnity/Editor/UI/UnitySkillsWindow.cs index 2d3574ba..8a689a4e 100644 --- a/SkillsForUnity/Editor/UI/UnitySkillsWindow.cs +++ b/SkillsForUnity/Editor/UI/UnitySkillsWindow.cs @@ -226,28 +226,29 @@ public void RefreshLocalization() public void RefreshSkillsList() { _skillsByCategory = new Dictionary>(); - var allTypes = SkillsCommon.GetAllLoadedTypes(); + // 与路由器使用相同的 Unity 编辑器索引,避免窗口刷新时再次全量枚举类型。 + var methods = TypeCache.GetMethodsWithAttribute(); - foreach (var type in allTypes) + foreach (var method in methods) { - foreach (var method in type.GetMethods(BindingFlags.Public | BindingFlags.Static)) - { - UnitySkillAttribute attr; - try { attr = method.GetCustomAttribute(); } - catch { continue; } - if (attr == null) continue; + if (!method.IsPublic || !method.IsStatic || method.DeclaringType == null) + continue; - var category = type.Name.Replace("Skills", ""); - if (!_skillsByCategory.ContainsKey(category)) - _skillsByCategory[category] = new List(); + UnitySkillAttribute attr; + try { attr = method.GetCustomAttribute(); } + catch { continue; } + if (attr == null) continue; - _skillsByCategory[category].Add(new SkillInfo - { - Name = attr.Name ?? method.Name, - Description = attr.Description ?? "", - Method = method - }); - } + var category = method.DeclaringType.Name.Replace("Skills", ""); + if (!_skillsByCategory.ContainsKey(category)) + _skillsByCategory[category] = new List(); + + _skillsByCategory[category].Add(new SkillInfo + { + Name = attr.Name ?? method.Name, + Description = attr.Description ?? "", + Method = method + }); } }