Q39: 如何设计战斗系统?
核心结论
战斗系统不是一个“伤害公式模块”,而是一套围绕战斗事件推进的权威状态机。
真正需要先设计清楚的是:
- 谁能发起战斗请求
- 请求进入后经过哪些校验
- 伤害、状态、仇恨、死亡怎样落地
- 结果如何广播和持久化
如果这些边界没定,单独把数值公式写得再漂亮,系统也会很脆。
一、战斗系统的核心职责
战斗系统通常要处理:
- 攻击和技能释放
- 命中与伤害结算
- Buff / Debuff 触发
- 仇恨与目标选择
- 死亡、复活、掉落
这意味着它本质上不是单点算法,而是一条事件链。
二、先明确权威归属
在线游戏里,战斗结果通常必须由服务端权威决定。
客户端可以:
- 提交输入
- 播放预表现
- 展示战斗反馈
但不能最终决定:
- 是否命中
- 造成多少伤害
- 是否死亡
- 是否掉落
否则外挂和状态分叉几乎不可避免。
三、一次战斗请求通常经历什么
典型流程一般包括:
- 输入到达
- 合法性校验
- 目标与空间条件校验
- 命中与伤害计算
- 状态应用
- 事件广播
- 关键结果持久化或流水记录
把这条链拉直以后,很多系统边界就清楚了。
四、战斗系统最容易混乱的几个点
1. 校验和计算混在一起
例如冷却、资源、目标有效性、距离判断,属于前置校验;暴击、减伤、护盾、吸血,属于结算逻辑。
如果混在一层里,后面很难维护。
2. 表现事件和权威事件混在一起
例如:
- “挥刀动画开始”更偏表现
- “命中成立并扣血”是权威事件
两者不能混成一条模糊逻辑。
3. 所有战斗效果都写死在技能里
这样会导致复用和组合能力非常差。更稳妥的设计通常会把效果拆成独立结算单元。
五、战斗系统通常要和哪些子系统联动
至少包括:
- 技能系统
- Buff 系统
- 属性系统
- AI 系统
- 掉落系统
- 同步与广播系统
所以战斗系统更像一个中枢,而不是孤立模块。
六、设计上更稳妥的思路
常见做法是把战斗拆成几层:
1. 输入层
接收玩家或 AI 的战斗请求。
2. 校验层
判断:
- 冷却是否满足
- 资源是否足够
- 目标是否有效
- 空间位置是否合法
3. 结算层
负责:
- 命中
- 伤害
- 吸收
- 格挡
- 暴击
- 护盾
4. 应用层
把结果真正写回对象状态,例如:
- 扣血
- 增减 Buff
- 切换死亡状态
5. 事件层
把结果广播给客户端和其他系统。
七、战斗系统为什么不能只靠公式驱动
伤害公式只是很小一部分。
很多复杂度来自:
- 多阶段技能
- 延迟生效
- 状态免疫
- 连锁触发
- 召唤物归属
- 死亡边界条件
这些都属于状态机和事件顺序问题,不只是公式问题。
八、工程上需要特别注意什么
1. 战斗结果要可追踪
关键链路最好能追出:
- 谁发起
- 何时命中
- 造成多少伤害
- 为什么被减免
这对排查数值异常非常重要。
2. 关键结果要有明确持久化边界
并不是所有战斗细节都要落库,但:
- 资产变动
- 死亡掉落
- 副本结算
通常要进入可靠链路。
3. 广播要分层
战斗内很多状态变化都是热点消息,不应全部按最重方式广播。
九、常见误区
1. 战斗系统就是伤害公式
远远不止。更多难点在状态推进和事件顺序。
2. 客户端看起来打中了,就应该算中
不对。最终命中判定必须由权威逻辑决定,必要时再配合延迟补偿。
3. 所有战斗逻辑都写进技能脚本最灵活
短期灵活,长期往往会失控,尤其是触发链和调试成本。
参考资料
- 各类 MMO / ARPG 战斗框架与权威结算实践资料
