一种类行为树方式的技能系统的设计思路
目录
先说技能系统.
首先,说明一下这个技能系统的目标,即实现支持市面上绝大部分rpg类型的游戏的技能系统.
可以是回合制,可以是即时制,可以有锁定,可以无锁定.
目标比较大,但是整个技能框架比较清晰.
分析需求:
首先以一个MMORPG游戏的一个常见的主动技能使用流程为例:
- 技能前摇,播放前摇动作,0.16s. 如果在此期间被打断,技能使用不成功,但是不进入冷却,也不消耗任何资源(MP,能量,无色小晶块)
- 等待前摇结束,接着开始播放技能施法动作,播放施法音效,持续时间1.2s.同时消耗所需要的资源. 被打断时,技能进入冷却
- 发射飞行道具(特效),对飞行道具添加伤害事件.该事件在击中可伤害目标时,会进入目标的被击中判定流程.该阶段不可被打断,因为是瞬间完成. 但飞行道具可以被抵挡. 该阶段结束后直接进入5阶段.
- 等到特效击中目标,对所有被击中的目标,造成伤害,播放击中特效,播放击中声音.
- 后摇阶段.该阶段可以被打断,打断后技能进入冷却.
- 技能结束.进入冷却.
上述技能是一个法师使用需要读条技能的场景.如果是不读条的技能,去掉上述第二阶段即可.如果是近战的技能,那么可能需要将第二阶段替换成间隔一定时间开启碰撞检测,而后直接进入第4阶段.(动作类游戏),也可能需要间隔一定时间后,判断如果目标还在攻击范围,直接进入第4阶段(MOBA类的近战瞬发类攻击)
可以看到,技能的流程基本就是一系列技能行为的组合.所以,我想籍此设计一套技能框架,由配置好的数据,或者调用技能框架暴露出的接口,来定义一套技能数据.再通过对应的逻辑层解析这些数据,执行技能.
经过一段时间的思考,我想出来了一套类似于组件式(ECS)模式的技能框架.它跟行为树有点类似.
系统设计
首先看它的数据层(E&C)结构:
如果将一整个技能比作一个实体(Entity),各种流程节点是它的Component,对这些流程节点的解析和执行是这些组件的System.
这样流程节点可以有:
- 延时节点: 上一阶段的流程节点执行完毕后,该节点延迟一定时间执行.该节点内的行为,如果需要目标输入的,这个目标可以是自己,也可以是之前的节点行为检测到的目标.
- 碰撞检测节点: 上一阶段的流程节点中,有可以发射碰撞检测的行为,该节点所有行为都在这个碰撞检测的行为检测到目标后触发.
- 循环开始节点: 该节点一般不附加行为,只是用来对之后的流程节点做循环用,一般用来实现闪电链,暴风雪这种持续多次的技能.
- 检测玩家输入节点: 该节点一般不附加行为,而是接受玩家的输入,产生结果供后续的节点调用.比如MOBA中选择一个方向使用技能.
- 条件检测节点: 该节点一般不附加行为,而是附加检测的条件,用以实现某些效果存在不同情况不同变化的技能.比如一个技能火球术,有30%的概率连续发射2枚.在火神附体的BUFF加持下,变成发射火龙(当然这种一般可以是做替换技能处理)
- 可编程节点: 暴露出各种行为的接口,让程序或者有能力的策划来用脚本编辑各种行为,主要目的是应对一些非常奇葩的情况,如果团队实力足够NB,类似于DOTA2那样,可以把这个完全交给策划用类似于lua的语言来写.
- ........
这些节点并不一定代表全部,完全可以根据项目需求来.
而对于节点下附加的各种行为来讲,节点本身是一个Entity,行为是Component,行为的解析执行逻辑则是对应的System.
每一个节点下的所有行为,都是并行执行的,每个行为可以再单独设定一定的延时执行时间,方便实现各种效果. 如果你有极为特殊的需求,也可以创建一个树形的行为结构.
这样的行为可以有:
- 播放音效.
- 发射飞行道具
- 播放BUFF携带特效
- 播放击中特效
- 播放角色动画
- 播放击退效果
- 震屏
- 复杂摄像机流程(一般用于摄像机特写)
- 范围碰撞检测(光环类被动技能,范围类主动技能等)
- 添加BUFF(这个是一个容器,可以容纳其他行为,比如改变数值,播放BUFF携带特效.同时还带有计时)
- 造成百分比伤害
- 造成固定伤害
- 添加DOT
- 添加HOT(这个可以设置为提高玩家的每秒HP回复率)
- 添加吸血效果(这个如果是全局性的,一般是直接改变玩家的吸血属性值,像LOL就是几种不同的吸血属性,有普攻吸血,有技能吸血)
- 添加击晕效果
- 添加冰冻效果
- 添加沉默效果
- 改变数值(可以直接改,也可以根据技能使用者的属性/技能目标的属性改)
- 提高技能效果(比如10秒内让玩家的普通攻击或者技能A必定暴击,暴击伤害固定xxxxx/根据玩家属性来,或者直接提升技能B效果30%,或者让技能C的效果附带吸血)
- .........
类似这样的行为数之不尽,要多少有多少.只要你的项目足够庞大.
有些行为需要目标输入/使用者输入/前阶段效果输入,有些不需要,这个可以在System层分为多个不同的接口.在流程节点的解析过程中,创建临时空间来保存整套技能使用中产生的临时数据,然后找到对应的接口派发就好了.
上述所有内容均基于技能使用条件都满足的情况下,事实上,我们还需要为这套技能系统添加一些额外的可**条件(ActiveCondition).用以判断是否可以执行该技能.
这样的条件有:
- 玩家是否主动使用(主动技能/被动技能的硬性分界线之一)
- 玩家是否装备了固定类型的武器(比如有的技能只能装备剑类武器才可以用)
- 玩家的属性是否达标(比如血量是否低于20%)
- 普通计时器计时是否结束(比如每2秒发射一道闪电,对周围5米目标造成xxxx伤害)
- 玩家没有进行普通攻击的计时器(比如LOL中的改版之前的岚切)
- .........
至于一些通用的资源消耗,可以在做一套消耗资源的行为以及检测资源是否满足的**条件.
技能系统在整个游戏的扩展:
事实上,这套系统强行划分成如此多的行为.不仅仅是用在技能系统中.也可以用在装备/道具系统中.当然,很多行为在技能中所特有的属性,在装备/道具中是用不到的,反之同理.这种划分一个基础行为,然后分别继承就好了.
比如某个道具用了后,15秒内增加玩家5%攻击力,实际上就是触发一个"添加BUFF"的行为.
又比如一个装备,有一堆增加的属性不说,还带几个特效:
- 特效A: 玩家没有进行普通攻击后的2秒,下一次普通攻击造成暴击,暴击伤害150%
这种实际上就是给玩家增加一个被动技能.
技能强化的实现:
在一些MMORPG游戏中,或者类似于暗黑这样的游戏中,技能拥有各种各样的强化,比如应用了强化A后,效果提升,应用了强化B后,技能范围加大等.
这些在这套技能系统中,可以通过设定流程节点/行为的开启/关闭来实现.