如何实现一个灵活、通用的战斗(技能)系统——数值系统(升级版)

本文介绍了如何通过设计数值修饰器和收集器,提升游戏数值系统的灵活性,以便于实现英雄生命值减少时暴击概率增加、屏蔽敌方增益效果等复杂技能效果。作者分享了代码示例和GitHub仓库链接,详细展示了从简化系统到应对复杂需求的转变过程。
项目GitHub仓库地址 : https://github.com/m969/EGamePlay
真是计划赶不上变化,没想到刚写完数值系统不久,就要对数值系统重写升级。 其实之前的那版数值系统在技能效果不是非常复杂的游戏里也是够用的了,可偏偏赶巧不巧就让我遇到了。
效果1 :现在我要实现的一个效果是英雄每损失10%的生命值会提供自身5%的暴击概率。这个效果虽然用之前的数值系统也是可以实现的,但无论我怎么实现都觉得不够简洁优雅。要么就是在效果有变的时候删掉之前的暴击buff加上新的暴击buff,要么就是减掉之前的暴击加成再加上新的暴击加成,这两个我都觉得不够简洁,理想情况下应该是直接用新的暴击加成覆盖掉旧的暴击加成然后刷新一下就行了。
效果2 :如果一个技能效果是屏蔽敌方所有的数值增益效果数秒,不是清除,只是暂时屏蔽,用之前的数值系统实现也是比较别扭。
想要实现直接用新数值覆盖旧数值实现buff刷新的话,我们需要让每一个buff数值变动都单独可控。之前的数值系统都是将数值变动加在一起的,做不到单独可控,所以我们现在需要做一下分离。 我们分离出一个数值修饰器的概念,具体的整形修饰器实现如下:
    
/// <summary> /// 整形修饰器 /// </summary> public class IntModifier { public int Value ; }
数值修饰器里只有一个字段Value,这个Value保存着单个数值变动的值,+10还是-10。 接着我们再写一个数值修饰器收集器来存储多个数值修饰器: |+10|-3|+6| | ---- | ---- |
    
/// <summary> /// 整形修饰器收集器 /// </summary> public class IntModifierCollector { public int TotalValue { get ; private set ; } private List < IntModifier > Modifiers { get ; } = new List < IntModifier > ( ) ; public int AddModifier ( IntModifier modifier ) { Modifiers . Add ( modifier ) ; Update ( ) ; return TotalValue ; } public int RemoveModifier ( IntModifier modifier ) { Modifiers . Remove ( modifier ) ; Update ( ) ; return TotalValue ; } public void Update ( ) { TotalValue = 0 ; foreach ( var item in Modifiers ) { TotalValue += item . Value ; } } }
这个收集器主要有两个接口,一个添加修饰器接口一个移除修饰器接口,每次做添加移除操作后都会刷新一下,计算出TotalValue总累计数值。 最后我们再基于这两个新类来整改我们的数值类:
    
/// <summary> /// 整形数值 /// </summary> public class IntNumeric { public int Value { get ; private set ; } public int baseValue { get ; private set ; } public int add { get ; private set ; } public int pctAdd { get ; private set ; } public int finalAdd { get ; private set ; } public int finalPctAdd { get ; private set ; } private IntModifierCollector AddCollector { get ; } = new IntModifierCollector ( ) ; private IntModifierCollector PctAddCollector { get ; } = new IntModifierCollector ( ) ; private IntModifierCollector FinalAddCollector { get ; } = new IntModifierCollector ( ) ; private IntModifierCollector FinalPctAddCollector { get ; } = new IntModifierCollector ( ) ; public void Initialize ( ) { baseValue = add = pctAdd = finalAdd = finalPctAdd = 0 ; } public int SetBase ( int value ) { baseValue = value ; Update ( ) ; return baseValue ; } public void AddAddModifier ( IntModifier modifier ) { add = AddCollector . AddModifier ( modifier ) ; Update ( ) ; } public void AddPctAddModifier ( IntModifier modifier ) { pctAdd = PctAddCollector . AddModifier ( modifier ) ; Update ( ) ; } public void AddFinalAddModifier ( IntModifier modifier ) { finalAdd = FinalAddCollector . AddModifier ( modifier ) ; Update ( ) ; } public void AddFinalPctAddModifier ( IntModifier modifier ) { finalPctAdd = FinalPctAddCollector . AddModifier ( modifier ) ; Update ( ) ; } public void RemoveAddModifier ( IntModifier modifier ) { add = AddCollector . RemoveModifier ( modifier ) ; Update ( ) ; } public void RemovePctAddModifier ( IntModifier modifier ) { pctAdd = PctAddCollector . RemoveModifier ( modifier ) ; Update ( ) ; } public void RemoveFinalAddModifier ( IntModifier modifier ) { finalAdd = FinalAddCollector . RemoveModifier ( modifier ) ; Update ( ) ; } public void RemoveFinalPctAddModifier ( IntModifier modifier ) { finalPctAdd = FinalPctAddCollector . RemoveModifier ( modifier ) ; Update ( ) ; } public void Update ( ) { var value1 = baseValue ; var value2 = ( value1 + add ) * ( 100 + pctAdd ) / 100f ; var value3 = ( value2 + finalAdd ) * ( 100 + finalPctAdd ) / 100f ; Value = ( int ) value3 ; } }
我们后续还可以在单个修饰器的数值有变动的时候走一下Update流程,这样就可以很简洁的实现前面的效果1了。 我们甚至可以给数值修饰器加一个Enable字段来标记这个数值变动当前是否生效,以此跳过某个数值变动的计算,这样再实现效果2就很方便了。
其实大致的流程没怎么变,主要是细化了其中的每个数值变动的阶段,让其变得更加可控,以应对更加复杂的需求。
最新完整的demo和代码在github仓库可取得。
往期文章:
如何实现一个灵活、通用的战斗(技能)系统——序章
如何实现一个灵活、通用的战斗(技能)系统——数值系统
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值