数值组件
提示
本文档介绍数值组件的内容大部分来自于ET Book的数值组件部分。
简介
数值组件是 ET 框架中一个重要的功能组件,它提供了一套完整的数值管理方案。主要功能包括:
- 数值的基础运算操作
- 数值变化事件监听与分发
设计思路
注意
在复杂的游戏系统(如MMORPG、MOBA)中,技能系统需要一套灵活的数值结构支持。一个角色可能包含多种属性:移动速度、力量、怒气、能量、集中值、魔法值、血量等。这些属性之间相互影响,且会受到buff的影响(绝对值增加、百分比增加等)。
传统方案及其局限
csharp
class Numeric
{
public int Hp;
public int MaxHp;
public int Speed;
public int Energy;
public int MaxEnergy;
public int Mp;
public int MaxMp;
}
这种设计存在以下问题:
- 不同职业可能使用不同属性系统(法师使用魔法值,盗贼使用能量值)
- 继承方案会导致类层次复杂
- 属性计算需要考虑多个影响因素
例如速度计算需要考虑:
csharp
class Numeric
{
public int Speed; // 速度最终值
public int SpeedInit; // 速度初始值
public int SpeedAdd; // 速度增加值
public int SpeedPct; // 速度增加百分比值
}
计算公式:
Speed = (SpeedInit + SpeedAdd) * (100 + SpeedPct) / 100
这种方案的主要问题:
- 类结构庞大
- 计算公式重复
- 属性配置不灵活
ET框架解决方案
ET框架采用Key-Value形式保存数值属性:
csharp
public enum NumericType
{
Max = 10000,
Speed = 1000,
SpeedBase = Speed * 10 + 1,
SpeedAdd = Speed * 10 + 2,
SpeedPct = Speed * 10 + 3,
SpeedFinalAdd = Speed * 10 + 4,
SpeedFinalPct = Speed * 10 + 5,
Hp = 1001,
HpBase = Hp * 10 + 1,
MaxHp = 1002,
MaxHpBase = MaxHp * 10 + 1,
MaxHpAdd = MaxHp * 10 + 2,
MaxHpPct = MaxHp * 10 + 3,
MaxHpFinalAdd = MaxHp * 10 + 4,
MaxHpFinalPct = MaxHp * 10 + 5,
}
核心实现:
csharp
public class NumericComponent: Component
{
public readonly Dictionary<int, int> NumericDic = new Dictionary<int, int>();
public void Update(NumericType numericType)
{
if (numericType > NumericType.Max)
{
return;
}
int final = (int) numericType / 10;
int bas = final * 10 + 1;
int add = final * 10 + 2;
int pct = final * 10 + 3;
int finalAdd = final * 10 + 4;
int finalPct = final * 10 + 5;
// final = (((base + add) * (100 + pct) / 100) + finalAdd) * (100 + finalPct) / 100;
this.NumericDic[final] = ((this.GetByKey(bas) + this.GetByKey(add)) * (100 + this.GetByKey(pct)) / 100 + this.GetByKey(finalAdd)) * (100 + this.GetByKey(finalPct)) / 100;
Game.EventSystem.Run(EventIdType.NumbericChange, this.Entity.Id, numericType, final);
}
}
优势:
- 灵活的属性管理:不同职业可以拥有不同属性
- 统一的计算公式:所有属性使用相同的计算逻辑
- 事件系统支持:属性变化可以触发相应事件
实际应用示例
监视HP数值变化:
csharp
namespace MH
{
[NumericWatcher(SceneType.Main, NumericType.Hp)]
public class NumericWatcher_HpChange : INumericWatcher
{
public void Run(Unit unit, NumbericChange args)
{
if (unit == null || unit.IsDisposed)
return;
var numericComponent = unit.GetComponent<NumericComponent>();
var currentHp = numericComponent[NumericType.Hp];
var maxHp = numericComponent[NumericType.MaxHp];
if (currentHp > maxHp)
numericComponent.SetNoEvent(NumericType.Hp, maxHp);
if (currentHp < 0)
numericComponent.SetNoEvent(NumericType.Hp, 0);
var hpBarComponent = unit.GetComponent<HpBarComponent>();
hpBarComponent.SetHpSliderHandler(unit);
}
}
}
技术支持
获取帮助
- 💬 加入QQ群讨论交流
(ET框架群)
: 474643097 - ⭐ 在GitHub上关注项目获取最新更新