因为三月份的时候开始上班了,通勤来回需要两个小时,到家实在是没有精力去写文章(不是因为什么懒惰或者拖延症!),所以之前的回合制战斗框架很久很有更新了,最近尝试在玩一个开着交通工具到处乱跑的游戏,边狱--,噢不是,崩铁,于是我打算蹭一波热度,哈哈。
这一篇讨论的是,如何基于GAS,实现一个回合制系统中通用的战斗流程管理系统,可以比较容易的实现一系列如亡语,追加攻击,回合前后的额外效果等,因为GAS已经实现的功能,后续也会很方便地用于扩展。
一开始还是贴一下我的回合制游戏文档,有兴趣的可以看看
回合制游戏战斗框架梳理jfpejv68no.feishu.cn/docx/YFATdbdQfouMtAxYqCCcacVPnkd
Action System的流程设计
既然提到了崩铁,那么就从几个游戏里面的例子开始分析流程。
游戏中邵,又说错了,三月七的队友如果在有护盾被攻击,三月七可以对目标追加一次攻击,这次攻击会插入到当前角色回合结束后。实现的方法应该是三月七身上有一个被动,监听队友受到伤害的消息,收到消息后,将反击技能抛入流程系统里,再回合结束后触发。
类似的还有怪物爆炸机器人,它在血量低于0后不会立即死亡,而是会先爆炸造成伤害,才会死亡,这里我认为应该是游戏的死亡是统一在回合结束后结算的,那么只需要在血量低于0的时候,触发爆炸技能,将这次行动插入到回合结束后的阶段,那么就会先释放爆炸技能,然后再结算死亡。
上述无论是反击还是自爆,我认为都可以抽象地理解为一个Action,一次表演,无论具体的功能是什么。整体的逻辑可以简略为:
- 某种条件下,某个Action被触发,插入到战斗流程中的某个阶段
- 每个阶段结束后,都会判断是否有可触发的Action,如果有,则依次进行表演。
- 重复1和2的流程
至于表演的内容是什么,战斗流程不需要关心,它只需要负责管理Action的开始和结束,让他们按照顺序依次的执行。以及接受添加和移除Action的消息。
那么Action的流程是不是和一个东西十分地相似?没错,就是我们的技能系统,所以完全可以使用GAS系统去写战斗流程和相关的表演,而不必去额外的写一堆没有必要的代码。
下图是一个简单的回合流程示意图。
- 在Action Manager中以TMap的形式存储着需要执行的Action sequence。
- 回合流程每个阶段发生改变时,会尝试获取当前阶段的Action队列
- Action队列如果不为空,则依次执行Action,每个Action可以理解为一个小阶段,比如追加攻击
- Action执行完毕后,进入下一个阶段,如果在过程中可以触发Action,则将需要添加的Action添加到Action Manager中对应阶段的Action队列
- 下个阶段开始会再次从ActionManager中获取Action队列,然后依次执行
- ......
拓展
这里再提一下我为什么认为游戏的逻辑也使用GAS,以及可能的使用方法。用GAS的思路去理解游戏逻辑,可以节省很大一部分的代码和脑细胞,我觉得是一个挺不错的方法。
可以将游戏流程视为技能,比如某场战斗中需求:当角色击杀10个敌人时,则会让BOSS出现。那么这个需求就可以通过两个GA来决定,一个被动可以监听击杀消息,击杀达到目标后,触发技能:生成BOSS
还有战斗可能会需要拆分为多个阶段,那么每个阶段可以用tag去表示,如果战斗管理器获取了一个Stage.1的tag,那么说明战斗进入第一阶段。
实现方法
ActionAbility
继承于GameplayAbility,为单个表演的基类技能。
我这么写的逻辑是为什么呢?我认为战斗的各个流程,可以理解为战斗管理器使用了一个游戏逻辑技能。
比如某个角色会触发追加攻击,那么对于这个角色来说,追加攻击是一个技能,使用技能的效果和表现可以在技能中实现和管理。
对于战斗流程来说,角色触发追加技,同样可以看作一个技能来管理,这个技能管理的是让XX角色使用XX技能,相应的UI展示,特效等等,也可以通过一个游戏逻辑技能实现。对于外部只关心一个流程的开始和结束,对应到的就是技能的Activate和End,耦合性也很低
然后按照更细分的功能,可以派生出追加攻击,亡语等,甚至于怪物的再次出场,BOSS的动画演出等等,也可以基于这套逻辑去实现。
ActionAbilitySystemComponent
继承于ASC,用于管理和使用ActionAbility。逻辑也十分简单。
使用一个Map存储各个阶段的Action队列
添加Action,将需要触发的Action写入对应的回合阶段中
获取对应回合阶段的Action Sequence
回合流程
下图是角色的回合开始的结算阶段
获取当前的Action Sequence,依次执行Action,全部执行完毕后跳转到下一步
使用案例
追加攻击的实现
可能有角色的技能是:杀死敌人以后,可以对目标再次释放一次普通攻击。
实现方法就是先有一个被动技能,监听角色的击杀消息
收到消息后,向ActionManager发送一个消息,添加一个Action_Ability,它的作用是让目标在指定的阶段使用指定的技能,在这里的数据为:在回合结束的时候,使用普通攻击的技能
Action_Ability的逻辑可以比较简单,我这里的代码首先判断了技能是否满足使用条件,获取技能的目标数据,然后启动技能,等待技能结束后,结束Action_Ability
其实重要的只有这里一小块
UI弹窗
在战斗的某个阶段,可能希望弹出一个UI窗口说明BOSS的技能,等待玩家浏览完毕关闭窗口后,继续战斗
代码也很简单,在我的项目里是,通过UI Manager打开输入的UI,监听UI的关闭消息,UI关闭以后结束技能,也就相当于Action的结束。UI的相关逻辑让UI自己去管理就好了