Unity角色能力系统:泛型Modifier动态填充Enum的实现问询
角色能力系统实现思路分析与优化建议
核心思路可行性判断
你的思路完全可行,核心逻辑——自定义特性标记可修改成员+泛型Modifier
- 动态枚举生成:可通过反射在编辑器模式下扫描T类型中带
[Modifiable]特性的成员,自动生成对应的ModifierTarget枚举(需处理编辑器重编译时的枚举更新逻辑,避免配置丢失)。 - 统一Modifier管理:泛型
Modifier<T>通过枚举值关联目标成员,配合ModifierCollection<T>类批量管理同类型Modifier,无需为每个字段单独维护列表。 - Modifier自身可修改:给
Modifier<T>的ModRatio字段标记[Modifiable],同时让Modifier<T>实现IAbilitySystem接口,即可让它被其他Modifier修改,逻辑自洽。
更优实现细节建议
1. 编辑器枚举生成优化
避免运行时反射开销,改为编辑器模式预处理:
- 编写自定义编辑器工具,在项目编译完成后自动扫描所有实现
IAbilitySystem的类型,提取带[Modifiable]的成员,生成对应的ModifierTarget枚举文件(存放于Editor目录外,保证运行时可用)。 - 给枚举值添加
[InspectorName]特性,让Inspector显示更友好的名称(如将MaxHealth显示为"最大生命值")。
2. ScriptableObject分层配置设计
拆分基础值与Modifier为不同ScriptableObject,提升复用性:
- BaseDataSO
:存储T类型的所有基础值(带 [Modifiable]的成员),作为能力/属性的基础模板。 - ModifierSO
:继承ScriptableObject,包含 ModifierTarget枚举选择、修改类型(加法/乘法/百分比)、修改值/比例,以及自身可配置的ModRatio。 - AbilitySystemSO
:组合 BaseDataSO<T>与多个ModifierSO<T>,作为最终能力配置入口,在Inspector中可直观添加/调整Modifier。
3. 数值计算高效实现
采用缓存+事件驱动避免重复遍历Modifier:
- 在
IAbilitySystem实现类中,为每个[Modifiable]成员维护缓存值,当Modifier添加/移除/修改时,触发重新计算并更新缓存。 - 提供
GetValue(ModifierTarget target)方法,直接返回缓存值,消除运行时反射开销。
4. 泛型逻辑拆分技巧
避免泛型类泛滥,用接口+抽象类拆分核心逻辑:
- 定义抽象类
BaseModifier,包含通用的修改类型、修改值、ModRatio等字段,以及基础数值计算逻辑。 - 泛型类
Modifier<T> : BaseModifier, IAbilitySystem仅负责关联ModifierTarget枚举与具体目标成员,复用BaseModifier的核心逻辑。
关键代码示例
自定义Modifiable特性
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)] public class ModifiableAttribute : Attribute { }
泛型Modifier基础结构
public abstract class BaseModifier : ScriptableObject { [Modifiable] public float ModRatio = 1f; // 支持被其他Modifier修改 public ModificationType Type; public float Value; } public enum ModificationType { Additive, Multiplicative, Percentage } public class Modifier<T> : BaseModifier where T : IAbilitySystem { public ModifierTarget Target; // 编辑器自动生成的枚举示例 public enum ModifierTarget { [InspectorName("最大生命值")] MaxHealth, [InspectorName("攻击速度")] AttackSpeed } }
编辑器枚举生成工具(简化版)
#if UNITY_EDITOR public static class ModifierEnumGenerator { [MenuItem("Tools/Generate Modifier Enums")] public static void GenerateEnums() { var types = AppDomain.CurrentDomain.GetAssemblies() .SelectMany(a => a.GetTypes()) .Where(t => typeof(IAbilitySystem).IsAssignableFrom(t) && !t.IsInterface && !t.IsAbstract); foreach (var type in types) { var modifiableMembers = type.GetMembers(BindingFlags.Public | BindingFlags.Instance) .Where(m => m.GetCustomAttribute<ModifiableAttribute>() != null); if (!modifiableMembers.Any()) continue; // 生成枚举代码并写入文件,此处省略字符串拼接逻辑 var enumCode = GenerateEnumCode(type.Name, modifiableMembers); File.WriteAllText(Path.Combine(Application.dataPath, $"Generated/{type.Name}ModifierTarget.cs"), enumCode); } UnityEditor.AssetDatabase.Refresh(); } } #endif
内容的提问来源于stack exchange,提问作者Tenkay
相关产品推荐
相关产品推荐

