ECGameplay|02 数值系统
概览
以攻击力为例,在大多数游戏中,无非是装备加成,以及BUFF(状态)加成两种
第一层攻击 = 初始攻击
第二层攻击 = (第一层攻击+装备固定加成)*(1+装备百分比加成)
第三层攻击 = (第二层攻击+BUFF固定加成)*(1+BUFF百分比加成)
数值抽象
不难抽象出一个数值类
FloatNumeric
namespace ECGameplay
{
public class FloatNumeric : Entity
{
// 最终数值
public float Value { get; private set; }
// 基础数值
public float baseValue { get; private set; }
// 装备固定加成
public float add { get; private set; }
// 装备百分比加成
public float pctAdd { get; private set; }
// BUFF固定加成
public float finalAdd { get; private set; }
// BUFF百分比加成
public float finalPctAdd { get; private set; }
}
}
我们可以直接增减add、pctAdd等,来间接控制最终数值
但是有一个问题,比如我们的装备A给我们增加了100固定攻击,装备B给我们增加了50固定攻击
那么我们的add会是150
但是,如果此时我希望暂时屏蔽装备2带来的加成呢?这时候,你会发现,我们无法区分add中的具体成分,即这部分攻击具体来自于哪儿
namespace ECGameplay
{
public class FloatNumeric
{
public float Value { get; private set; }
public float baseValue { get; private set; }
private FloatModifierCollection AddCollection { get; } = new FloatModifierCollection();
private FloatModifierCollection PctAddCollection { get; } = new FloatModifierCollection();
private FloatModifierCollection FinalAddCollection { get; } = new FloatModifierCollection();
private FloatModifierCollection FinalPctAddCollection { get; } = new FloatModifierCollection();
public void SetBaseValue(float baseValue)
{
this.baseValue = baseValue;
Refresh();
}
public void AddAddModifier(FloatModifier modifier)
{
AddCollection.AddModifier(modifier);
Refresh();
}
public void AddPctAddModifier(FloatModifier modifier)
{
PctAddCollection.AddModifier(modifier);
Refresh();
}
public void AddFinalAddModifier(FloatModifier modifier)
{
FinalAddCollection.AddModifier(modifier);
Refresh();
}
public void AddFinalPctAddModifier(FloatModifier modifier)
{
FinalPctAddCollection.AddModifier(modifier);
Refresh();
}
public void RemoveAddModifier(FloatModifier modifier)
{
AddCollection.RemoveModifier(modifier);
Refresh();
}
public void RemovePctAddModifier(FloatModifier modifier)
{
PctAddCollection.RemoveModifier(modifier);
Refresh();
}
public void RemoveFinalAddModifier(FloatModifier modifier)
{
FinalAddCollection.RemoveModifier(modifier);
Refresh();
}
public void RemoveFinalPctAddModifier(FloatModifier modifier)
{
FinalPctAddCollection.RemoveModifier(modifier);
Refresh();
}
private void Refresh()
{
var value1 = baseValue;
var value2 = (value1 + AddCollection.TotalValue) * (100 + PctAddCollection.TotalValue) / 100f;
var value3 = (value2 + FinalAddCollection.TotalValue) * (100 + FinalPctAddCollection.TotalValue) / 100f;
Value = value3;
}
}
}
FloatModifier
一个数值修饰器,自身没啥用
namespace ECGameplay
{
public class FloatModifier
{
// Id,用于区分不同的修饰器
public int Id;
// 修饰值
public float Value;
}
}
FloatModifierCollection
修饰器收集器,整合所有的数值修饰器
namespace ECGameplay
{
public class FloatModifierCollection
{
public float TotalValue { get; private set; }
// 所有的修饰器
private List<FloatModifier> Modifiers { get; } = new List<FloatModifier>();
public void AddModifier(FloatModifier modifier)
{
Modifiers.Add(modifier);
Refresh();
}
public void RemoveModifier(FloatModifier modifier)
{
Modifiers.Remove(modifier);
Refresh();
}
private void Refresh()
{
TotalValue = 0;
foreach (var item in Modifiers)
{
TotalValue += item.Value;
}
}
}
}
AttributeComponent
namespace ECGameplay
{
public class AttributeComponent : Component
{
// 移动速度
public FloatNumeric MoveSpeed { get; set; } = new ();
// 当前生命值
public FloatNumeric HealthPoint { get; set; } = new ();
// 生命值上限
public FloatNumeric HealthPointMax { get; set; } = new ();
// 攻击力
public FloatNumeric Attack { get; set; } = new ();
// 防御力(护甲)
public FloatNumeric Defense { get; set; } = new ();
// 法术强度
public FloatNumeric AbilityPower { get; set; } = new ();
// 魔法抗性
public FloatNumeric SpellResistance { get; set; } = new ();
// 暴击概率
public FloatNumeric CriticalProbability { get; set; } = new ();
// 暴击伤害
public FloatNumeric CauseDamage { get; set; } = new ();
public override void Awake()
{
MoveSpeed.SetBaseValue(1);
HealthPoint.SetBaseValue(99_999);
HealthPointMax.SetBaseValue(99_999);
Attack.SetBaseValue(1000);
Defense.SetBaseValue(300);
AbilityPower.SetBaseValue(0);
SpellResistance.SetBaseValue(300);
CriticalProbability.SetBaseValue(0.5f);
CauseDamage.SetBaseValue(1.5f);
}
}
}
测试
public class Test : MonoBehaviour
{
private MasterEntity MasterEntity => MasterEntity.Instance;
public class TestEntity : Entity
{
public override void Update()
{
Debug.Log(GetComponent<AttributeComponent>()?.HealthPoint.Value);
}
}
private void Start()
{
var entity = MasterEntity.AddChild<TestEntity>();
entity.AddComponent<UpdateComponent>();
entity.AddComponent<AttributeComponent>();
}
private void Update()
{
MasterEntity.Update();
}
}