50行代码实现魔兽级属性系统:ET数值组件设计解密
【免费下载链接】ET Unity3D 客户端和 C# 服务器框架。 项目地址: https://gitcode.com/GitHub_Trending/et/ET
你还在为角色属性系统臃肿不堪而烦恼?传统OOP设计让每个职业都需要单独的数值类,新增属性要改十几个文件?本文将带你拆解ET框架的KeyValue数值设计方案,用不到50行核心代码实现可无限扩展的复杂属性系统,彻底解决MMO/RPG游戏开发中的数值管理难题。
读完本文你将掌握:
- 如何用枚举定义属性类型避免魔法值
- KeyValue结构如何支撑5层数值叠加计算
- 一行代码实现属性变化事件监听
- 跨职业/种族的数值系统通用方案
传统数值设计的3大痛点
普通游戏开发中,我们习惯用这样的类定义角色属性:
class Numeric {
public int Speed;
public int SpeedInit;
public int SpeedAdd;
public int SpeedPct;
// ... 其他30+属性
}
这种设计在《魔兽世界》级别的复杂游戏中会迅速崩溃:
痛点1:职业差异化导致类爆炸
法师需要Mp属性,盗贼需要Energy属性,10个职业就会衍生出10个数值子类。当新增"怒气值"系统时,所有近战职业的数值类都要修改。
痛点2:属性计算逻辑重复
每种属性都需要类似Speed = (SpeedInit + SpeedAdd) * (100 + SpeedPct) / 100的计算代码,30种属性就要写30遍重复逻辑。
痛点3:Buff系统难以维护
给角色添加"增加20%移动速度"的Buff时,需要专门编写代码找到SpeedPct字段并修改,新增Buff类型就要新增处理逻辑。
ET的KeyValue设计革命
ET框架采用枚举+字典的创新结构,彻底解决了传统设计的痛点。核心代码位于Book/5.6数值组件设计.md,让我们逐层拆解实现原理。
1. 枚举定义属性类型体系
ET用NumericType枚举构建了属性的"基因序列",每个主属性派生出5个子属性:
public enum NumericType {
Speed = 1000, // 最终速度值
SpeedBase = Speed * 10 + 1, // 基础值
SpeedAdd = Speed * 10 + 2, // 增加值
SpeedPct = Speed * 10 + 3, // 百分比增加值
SpeedFinalAdd = Speed * 10 + 4, // 最终增加值
SpeedFinalPct = Speed * 10 + 5 // 最终百分比值
}
这种设计让每个属性自动拥有5层计算维度,新增"暴击率"只需添加:
Crit = 1005,
CritBase = Crit * 10 + 1,
// ... 其他4个子属性
2. 字典存储实现动态属性
NumericComponent使用字典存储所有属性值,避免了类字段膨胀:
public class NumericComponent: Component {
public readonly Dictionary<int, int> NumericDic = new Dictionary<int, int>();
public int this[NumericType numericType] {
get => GetByKey((int) numericType);
set {
NumericDic[(int)numericType] = value;
Update(numericType); // 自动触发计算
}
}
}
法师角色不会存储Energy相关的键值对,盗贼不会存储Mp相关键值,实现了零冗余存储。
3. 万能计算公式统一逻辑
通过数学规律将所有属性计算统一为一个公式:
final = (((base + add) * (100 + pct) / 100) + finalAdd) * (100 + finalPct) / 100;
对应代码实现:
public void Update(NumericType numericType) {
int final = (int) numericType / 10; // 获取主属性ID
int bas = final * 10 + 1; // 基础值ID
int add = final * 10 + 2; // 增加值ID
// ... 其他子属性ID
NumericDic[final] = ((GetByKey(bas) + GetByKey(add)) *
(100 + GetByKey(pct)) / 100 +
GetByKey(finalAdd)) *
(100 + GetByKey(finalPct)) / 100;
}
这行代码让所有属性自动支持5层叠加计算,无论是速度、生命值还是魔法值,都遵循同一套计算逻辑。
实战:3步实现Buff系统
基于ET数值组件,给角色添加"增加20%移动速度"的Buff只需3步:
1. 定义Buff配置
在配置表中指定Buff影响的数值类型和值:
{
"Id": 1001,
"Name": "疾跑",
"NumericType": "SpeedPct",
"Value": 20
}
2. 应用Buff效果
当Buff激活时,直接修改对应子属性:
NumericComponent numeric = unit.GetComponent<NumericComponent>();
numeric[NumericType.SpeedPct] += 20; // 自动触发Update计算
3. 监听属性变化
成就系统通过事件监听属性变化:
[NumericWatcher(NumericType.Hp)]
public class NumericWatcher_Hp : INumericWatcher {
public void Run(long id, int value) {
if (value > 1000) {
// 触发"长寿大师"成就
}
}
}
性能对比:传统设计 vs ET设计
| 指标 | 传统OOP设计 | ET KeyValue设计 |
|---|---|---|
| 新增属性代码量 | 10+文件修改 | 1行枚举定义 |
| 内存占用 | 固定30+字段 | 按需存储 |
| Buff系统复杂度 | O(n) | O(1) |
| 跨职业兼容性 | 需继承扩展 | 天然支持 |
扩展阅读与资源
掌握这套设计后,无论是《原神》的元素反应系统,还是《英雄联盟》的装备属性叠加,都能通过扩展NumericType枚举轻松实现。下一篇我们将深入探讨如何基于此系统实现技能效果的实时计算,敬请关注。
【免费下载链接】ET Unity3D 客户端和 C# 服务器框架。 项目地址: https://gitcode.com/GitHub_Trending/et/ET
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



