Skip to content

技能系统 ​

Category ​

system / 玩法系统。节点定位:把「技能」拆成配置、时间轴、目标选择、效果管线、Buff 五个部件,回答每个部件放哪一层、按什么口径扩展。同步与裁决的细节在 server 树(sync/08),战斗数值口径在 numerical 树——本页只管部件组成与扩展边界。

Definition ​

技能系统的本质是一条效果生产管线:一次施法从输入出发,经目标选择、时间轴推进、效果实例化、Buff 与被动挂载,最终改变实体状态并对外广播。技能系统的质量不看「写了多少个技能」,看新技能能否主要靠组合已有部件完成——技能数量增长不等于代码增长,这是部件化设计的唯一目标。

Problem ​

技能系统的坑集中在三处,且互相放大:

  • 边界:表现、判定、数值混写在一起。技能脚本里既画特效又算伤害又做目标判定,任何一处改动都要回归全部技能。
  • 增长:按「每个技能一个脚本」起步的项目,第三十个技能开始复制粘贴,第一百个技能时没人敢动公共代码——因为没人说得清哪个技能依赖了哪个副作用。
  • 裁决:同步、回放、重连「之后再补」。判定时刻、命中窗口、Buff 迭代顺序没有在系统层先定,补的时候每个技能的裁决都说不清(过程同步的展开见 同步与技能)。

先定部件边界,再谈实现;顺序反了的系统,最后都长成「每次加内容都像在拆炸弹」。

Algorithm ​

五部件拆分 ​

部件职责归属常见错位
配置消耗/冷却/前后摇/目标规则 id/效果序列 id策划表或 JSON,不是代码技能参数硬编码进脚本,改数值要发版
时间轴前摇 → 生效点 → 后摇的推进客户端表现先行,服务端按权威时间轴裁决生效点跟动画走,客户端一卡判定就漂移
目标选择指向性/非指向/AOE/自选的规则集规则是配置数据,执行在服务端复验目标列表由客户端上报且不复验
效果管线原子效果(伤害/治疗/位移/上 Buff/召唤)的有序组合服务端为权威执行方效果类型写死枚举,新类型改全局 switch
Buff 与被动统一事件流上的监听与周期效果服务端权威、客户端表现层预演Buff 字段全部进同步快照,带宽被状态淹掉
  • 配置层:技能 = 数据。一份技能配置的合理形态是「入口字段 + 效果序列引用」,效果序列本身也是配置。什么进表、什么进脚本的分界,见 配置驱动与脚本驱动。
  • 时间轴:生效点是整个技能的裁决锚——它决定客户端预测与服务器纠正的行为(前摇被打断、生效点之前死亡是否生效)。时间轴与动画解耦:动画可以丢帧,时间轴不丢。
  • 目标选择:选目标规则本身是可配置数据(半径/夹角/数量/友方过滤),执行永远在服务端复验——客户端上报的只能当意图。
  • 效果管线:效果是原子操作的有序列表,可组合、可插入。伤害加成、暴击、减免都是管线上的插件,而不是散落在技能代码里的 if。
  • Buff 与被动:被动是监听统一事件流(onCast/onHit/onTick)的零时长技能。Buff 与被动共用同一套事件流,新增机制才不需要新的执行通路。

扩展性四问(验收口径) ​

  1. 新技能能否主要靠组合已有部件完成?
  2. 新效果类型能否局部扩展,而不是改全局分发?
  3. 技能、Buff、被动、召唤物是否复用统一事件流?
  4. 线上问题能否定位到具体施法实例、具体目标选择、具体效果结算?

四问全过,技能数量增长才不伴随维护成本增长。这四问的同步侧展开(帧对齐、施法流程、Buff 同步边界)在 server 树 sync/08。

取舍 ​

部件化的代价是前期抽象成本:五个部件的接口先于第一个技能存在。小项目(技能总量个位数、不迭代)可以退化成「配置 + 一份技能脚本」,但要守住一条线:判定与效果执行放服务端,配置与表现放客户端——这条线破了,后面全部返工。技能的数值口径(伤害公式、成长曲线)不归本页,见 战斗数值。

Used By ​

  • BigWorld(commit 088d3b84,路径相对 programming/bigworld/):实体脚本层是嵌入式 Python(README.md:21),实体定义由 lib/entitydef/ 在引擎侧承载——技能作为实体方法写在脚本层,只做「选目标 + 起效果」;判定、AOI 裁剪与广播由 cellapp 承担,脚本不碰同步。
  • skynet(commit 64391f7):战斗做成独立 Lua 服务——22 个内置服务各司一职(service/ 目录),业务服务经 skynet.launch 拉起(service/launcher.lua:95),单服务内消息串行语义天然消灭并发写竞争,效果管线的执行顺序可复现。
  • Colyseus(commit e620123):引擎不提供任何技能设施——房间 tick 默认 60fps 推进模拟、20fps 推进 patch(packages/core/src/Room.ts:57-58),五部件全部在房间类里显式自建;适合作为「部件边界自查」的最小对照面。

关系链:部件拆分 → 分层归属 → 扩展口径 → 引擎落地 → 数值与同步的下游。逐段回答「为什么需要下一个」:

  • 拆分之后要定归属:每个部件的客户端/服务端分工与裁决方,是前后端边界在技能上的投影(见 客户端职责边界)。
  • 归属定了要给增长立口径:扩展性四问是评审时的验收清单,不是口号。
  • 口径过了要落引擎:三家引擎对「技能设施」的三种态度(脚本实体/服务化/全自建)给出落地光谱。
  • 落地之后进下游:数值口径在 numerical 树、过程同步在 server 树,技能产出的生效入口是 结算。

同口径姊妹节点:排行榜、队伍匹配、PVP 匹配(同为玩法系统,先立口径再谈实现的同一套方法)。

Reference ​

  • 本页为工程经验归纳;三家引擎事实以文内 commit 锚定的源码引用为准
  • 过程同步与技能的帧对齐、Buff 同步边界:server 树 sync/08
  • 术语对照:Ability/Skill(技能)、Cast Time(施法时间)、Effect Pipeline(效果管线)、Buff/Debuff(增益/减益)

游戏知识体系