跳转至

基于配置&逻辑-数据分离【技能系统】初总结

眨眼间就已经到第两段实习了,在此之间零零总总做过系统UI、战斗逻辑、工具开发、渲染开发、平台化相关的内容...涉及很多但方面很散。在求职间隙中仿照之前的商业项目结构写了不少战斗开发的东西,打算先在战斗方向做一个总结,深化一下学到的内容。

一 技能系统预览

这是我根据目前对技能系统的开发与了解罗列出的东西,若有改进建议欢迎告知~

  • 技能系统核心机制技能、BUFF、子弹 三者的结合体
  • 逻辑与表现分离: 这是网络同步游戏的基础,尤其是在帧同步游戏(如moba),必须要划分逻辑层做确定性物理模拟,表现层做动画、特效、运动插值效果。
  • 网络服务: 帧同步、状态同步、状态帧同步的适配,一个优秀的战斗系统当然需要做到网络能跑、单机也能跑。
  • 实体单位分类: 比如一些目标具有共有机制如普攻、血量变更、移动、东海等通用机制。而子弹、BUFF只需要移动、特效这些东西, 需要对实体进行细分减少重复架构。
  • 移动逻辑:逻辑移动、位置同步、预测与平滑插值等,也是非常重要的一环。
  • 属性管理:提供所有的数据调用接口,供外部控制。
  • 目标检索:从实体管理类筛选技能作用的目标,将目标返回给技能进行相关功能的计算。
  • 技能循环: 技能的状态切换,如搜索、创建、激发、后摇(根据游戏差异可以更加定制化),在此之间还要考虑表现层的变化、BUFF、子弹的触发机制等。
  • BUFF机制:本质上为定时器+多个状态,实体身上会有个BUFF列表用来提供挂载,理论上,BUFF能干任何事
  • 子弹机制:本质上为定时器+运动逻辑+多个状态,根据类型还可以细分跟踪、轨迹、穿透等多种子弹类型。
  • 伤害机制: 指定触发者和目标,传入技能配置,根据当前BUFF和具体配置的伤害公式计算出伤害(治愈)。
  • 控制效果:事件驱动控制计数、设置优先级,技能打断与恢复等效果。
  • 触发机制: 大部分就是被动和BUFF带来的, 注册+触发执行。而被动,可以将其当做一种永久持续的BUFF效果。
  • 日志系统: 日志系统能尽量记住大部分的战斗、状态变更数据。便于DEBUG和追踪。
  • 打击手感: 飘字分帧、相机震动与视角转换、血条表现、顿帧、硬直、连招缓存、动作共渡、根运动匹配等等,优化很多就不一一列举了。
  • UI系统: 血条变化、飘字、buff显示、按键显示、死亡界面等,是战斗环节必不可少的地方
  • 定点数物理库与全局统一随机算法:这是帧同步游戏的基础与重中之重,是保证同步的基础。可能比较专,这里还是提一下。

还有一些值得深入的东西,可能因为更偏重团队开发或者设计到大项目的性能优化还没有怎么去做,但不代表不重要: - EXCEL配置表工具: 这个主要是为了团队开发,EXCEL写一写就可以转为代码供开发者调用,且比代码易读。不过个人开发时比较喜欢直接代码配置,减少刷表时间,本质上还是转为代码来提供调用。 - AI与行为树: 人机、怪物等AI实现,包括使用行为树将技能做成节点交给策划去调整。复用性更高,易读性更强,更易调整。 - 技能编辑器:技能循环在商业化项目的更直观的表现,可以利用时间轴更加定制化技能循环逻辑与表现处理。代价也是大量UI性质的设计,个人开发暂时没打算做。 - 资源加载:比如特效、音效、动作 ,对象池的设计等,好的资源加载能大幅优化战斗系统的性能。

技能循环逻辑

1. 找目标

对于有目标的技能第一步肯定是找目标,无目标技能则可以跳过这一大步。

2.技能释放

目标技能: - 前摇处理 - 前摇计时(无前摇则直接触发后续逻辑) - 技能生效: - 再判目标 (有前摇需要技能生效时再判断) - 附着BUFF - 后摇处理

无目标技能: - 前摇处理 - 前摇计时(无前摇则直接触发后续逻辑) - 技能生效: - 弹道技能发射(前提是有配置) - 附着BUFF - 后摇处理

查找计算类

这里用来存储场景中所有的实体,供于查找计算。

直接列表查找了,后续可以考虑四叉树或者AABB空间优化。

Skill添加流程

看起来要比BUFF简单,不用单独写新的技能类和单独的逻辑处理。技能本身就是配置+统一逻辑形成的

  • 设置一个技能配置
  • 添加一个技能:在ResSvc的GetSkillConfigByID添加,绑定skillID和skill配置关系

操作中断与恢复

注意输入方向和角度朝向是两个值,前者是代表着位移信息的向量,后者仅是旋转方向。后者会受到前者影响。

  • 改变角度朝向:技能前摇施展时对准目标。实现了仅改变角度但不移动
  • 模拟输入方向:不修改UI方向直接修正实际方向。一般传入0直接截停移动(小伙立正了),具体情况目前有:
    • 硬控的瞬间
    • 死亡的瞬间
    • 技能前摇施展瞬间
  • 恢复输入:由于没有修改UI方向,所以可以直接缓存UI方向从UI方向恢复

  • 实际发送移动输入方向为0:也是一种截停的逻辑

    • 比如移动攻击超出搜素范围,或者移动到技能可以生效的范围。

注意区分上面两种截停,前者一般是被某种方式打断造成的,后面那种是确实要改变移动为静止站立。

  • 负面硬控状态正常输入时:UI方向可改变,但检测到有硬控,所以实际方向保持为0,且不允许修改

关于 前摇、后摇、技能打断的思考

目前游戏的技能系统直接将前摇结束进行技能释放,然后进入后摇,后摇阶段即可被直接打断。这会造成技能过早被打断,动画片段展示过于割裂。 - 解决办法:延长前摇时间,但这可能会导致出伤、挂buff过慢的情景。

对于一些动作高要求,动作向的游戏,前摇结束了之后应该过一段时间才能进行直接打断。 - 解决办法:加一个新的时间字段,超过这个时间才进入后摇,允许被打断。

缺点就是增加了配置与开发的难度。

常用技能功能实现

1. 移动停止

将InputDir设置为0,来关闭预测移动

2.禁止移动操作

一个bool函数,只有为true时客户端才运行发送移动操作指令,同时按键操作虽然保持UI更新但必须防止实际输入方向发生改变。

禁止移动操作情况通常有下面这些情况: - 负面状态影响:未被眩晕/击飞(检查状态计数) - 技能施法前摇:施法完成前不允许移动。(遍历所有技能状态)

3.被动技能实现

这个其实是永久BUFF,所以右转隔壁BUFF实现去。

4. 技能禁止

有些状态会导致技能无法被释放,所有UI被关上,无法发送SkillKey。 - 状态判断:沉默、击飞、眩晕 - 技能前摇:其他技能在做前摇的时候不应该放技能。 - 技能没准备好:遍历技能,如果有None状态技能才能使用技能 (好像前摇就是肯定没准备好,后面再看看)

5. 判断是否是玩家

根据posIndex 是否等于 GameRoot中存储的selfIndex来判断。 - 用于一些只有自己才有的功能实现:比如UI。

6. 技能打断重置

技能开始时也会触发一个计时器让技能结束后动作回到静置状态。 当释放下个技能或者中途变移动攻击时要避免被打断到静置。因此: - 释放新技能时:清空已有的技能打断回调。 - 移动回调新增:清空已有的技能打断回调。 这样就可以实现技能打断重置的效果。

Comments