让我们来看看Buff模块罢!
看了一下buff模块设计,这个感觉怪怪的,和通常的Buff模块的设计方式有些不一样。
首先是设计了一个Buff主体。
//buff主体类型
public enum BuffSubjectType
{
Enemy,
Tower
}
也就是Buff效果对象。
BuffManager的初始化
public BuffSubjectType subjectType = BuffSubjectType.Enemy;
private Enemy enemy;
private EnemyData originData;
private Tower tower;
private TowerData towerOrginData;
private void Start()
{
if (subjectType == BuffSubjectType.Enemy)
{
enemy = GetComponent<Enemy>();
originData = DataManager.GetInstance().GetEnemyDataByID(enemy.id);
}
else if (subjectType == BuffSubjectType.Tower)
{
tower = GetComponent<Tower>();
towerOrginData = DataManager.GetInstance().GetTowerDataByID(tower.id);
}
}
初始化也是初始化俩个类型,也就是说这个BuffManager会针对不同的主体类型有不同的处理。
BuffManager是公用的。下面是处理方式。
//每帧获取多个buff的不同修改数值的最高值或者最低值
void BuffPropertyChangeCheck()
{
if (subjectType == BuffSubjectType.Enemy)
{
enemy.data.speed = GetFinalChangePropertyMinValue(originData.speed, GetChangePropertyMinValueByType(BuffWorkTypes.ChangeSpeed));
enemy.data.antiArm = GetFinalChangePropertyMaxValue(originData.antiArm, GetChangePropertyMaxValueByType(BuffWorkTypes.ChangeAntiArm));
enemy.data.antiElct = GetFinalChangePropertyMaxValue(originData.antiElct, GetChangePropertyMaxValueByType(BuffWorkTypes.ChangeAntiElct));
enemy.data.antiLas = GetFinalChangePropertyMaxValue(originData.antiLas, GetChangePropertyMaxValueByType(BuffWorkTypes.ChangeAntiLas));
}
else if (subjectType == BuffSubjectType.Tower)
{
tower.data.attackPower = GetFinalChangePropertyMaxValue(towerOrginData.attackPower, GetChangePropertyMaxValueByType(BuffWorkTypes.ChangeAttackValue));
tower.data.attackSpeedMul = GetFinalChangePropertyMaxValue(towerOrginData.attackSpeedMul, GetChangePropertyMaxValueByType(BuffWorkTypes.ChangeAttackSpeed));
}
}
//增益效果最大值
float GetChangePropertyMaxValueByType(BuffWorkTypes type)
{
float maxValue = 0;
foreach (BuffSystemBase buff in m_Buffs)
{
if (buff.BuffData.BelongBuffSystemType == BuffSystemType.ChangePropertyBuffSystem)
{
ChangePropertyBuffData tempChangePropertyBuffData = buff.BuffData as ChangePropertyBuffData;
if (tempChangePropertyBuffData.TheValueWillBeAdded > maxValue && buff.BuffData.BuffWorkType == type)
{
maxValue = tempChangePropertyBuffData.TheValueWillBeAdded;
}
}
}
return maxValue;
}
然后查看资产引用。
都是绑定在Tower的预制体上。也就是这个BuffManager不是全局的BuffManager,而是局部的BuffManager。
另外这个BuffManager只在Tower预制体上有引用,但是BuffManager又设置了俩种主体。
猜猜Enemy怎么使用BuffManager?
答案是通过Bullet使用。
这是Bullet的Update。
private void Update()
{
if (type == BulletType.Target)
{
TargetModeUpdate();
}
else if (type == BulletType.Line)
{
LineModeUpdate();
}
}
根据子弹类型的不同有俩种处理方式。
其中ChangePropertyBuffSystem是一个Buff效应器,类似一个Handler。
其基类是这个。
public enum BuffState
{
//等待执行
Waiting,
//正在执行
Running,
//buff结束
Finished,
}
public abstract class BuffSystemBase
{
//buff当前状态
public BuffState BuffState;
//最多持续到什么时候
public float MaxLimitTime;
public BuffDataBase BuffData;
//来自哪个攻击者
public Attacker Attacker;
//敌人
public Enemy Enemy;
//初始化buff数据
//buffData=buff数据,attacker= 攻击者,enemy=敌人
public abstract void OnInit(BuffDataBase buffData, Attacker attacker, Enemy enemy);
//buff触发
public abstract void OnExecute();
//buff持续状态每帧调用
public virtual void OnUpdate()
{ }
//buff结束的时候
public abstract void OnFinished();
//刷新buff的状态
public virtual void OnRefresh()
{ }
}
也就是说Bullet里的代码就是根据子弹所携带的BuffData配置数据,动态new一个修改属性的buff效应器添加到Buff列表, 然后通过BuffManager对敌方单位进行属性修正。
看到这里我只能说,真是豪放的实现方式啊。
长见识了。
通常的Buff模块的做法
通常Buff的做法是定义一个IBuffContainer接口作为Buff容器添加给每个可以拥有Buff的单位…
public interface IBuffContainer
{
List<Buff> BuffList { get; set; }
void OnBuffChanged();
void OnBuffTick();
}
然后通过一个全局的BuffManager进行管理…
算了,我这里贴一个之前我看过的讲的比较好的通用Buff模块教程链接吧
[Unity游戏教程]Buff系统的数据结构_哔哩哔哩_bilibili