Steam 游戏伤害结算管线实战:2021 年 7 月个人项目如何处理命中、抗性、暴击、护盾和日志

面向个人战斗游戏的伤害结算教程,覆盖命中事件、伤害类型、抗性、护盾、暴击、状态效果、浮字、日志和 QA。

为什么需要伤害管线

个人游戏早期常把伤害写成 target.hp -= 10。等系统变多后,问题就来了:武器有伤害类型,敌人有护甲,玩家有护盾,暴击会加成,状态效果会增伤,难度会调整,格挡会减伤,成就要统计击杀。伤害逻辑如果散落在武器脚本、敌人脚本和 UI 里,很快会变得不可解释。

伤害结算管线的目标是让每一次伤害都走同一条流程:命中生成事件,收集上下文,计算基础伤害,应用修正,更新生命,触发反馈,写日志。这样玩家觉得不公平时,开发者能追踪原因。

伤害事件

伤害从事件开始,而不是直接改血量。事件包含:

字段说明
source攻击者或陷阱
target受击对象
base_damage基础伤害
damage_type物理、火焰、毒等
hit_position命中特效位置
flags可暴击、可格挡、无视护盾
context武器、技能、难度、场景

有了事件,伤害系统可以统一处理武器、陷阱、环境、状态效果。UI 和音效也能从事件结果中读取信息。

结算顺序

结算顺序要固定,并写进文档。例如:

  1. 检查目标是否可受伤。
  2. 检查闪避、无敌帧、格挡。
  3. 计算暴击和攻击者加成。
  4. 应用目标抗性和护甲。
  5. 应用难度倍率。
  6. 扣护盾。
  7. 扣生命。
  8. 触发状态效果。
  9. 触发死亡或受击反馈。
  10. 写战斗日志。

顺序不同,结果会不同。比如先扣护盾还是先减抗性,玩家感受和数值平衡都会变化。固定顺序能减少争议。

伤害类型和抗性

伤害类型不要太多。每多一种类型,就需要 UI、敌人配置、道具说明和测试。小项目可以从物理、火焰、毒、真实伤害几类开始。

抗性表:

敌人物理火焰
普通机器人1.01.20.2
木质怪0.91.51.0
石像0.70.80.0

倍率要在 UI 或图鉴中解释,不一定显示具体数字,但玩家要能通过反馈理解“火焰更有效”。

护盾和生命

护盾规则要清楚:护盾是否先于生命扣除,是否有伤害类型绕过护盾,护盾破裂是否有硬直,溢出伤害是否进入生命。

示例:

规则决策
普通伤害先扣护盾
毒伤害绕过护盾
破盾触发短硬直
溢出进入生命

规则写清后,玩家看到护盾破裂和生命下降才不会困惑。

暴击和随机

暴击是常见系统,但要谨慎。暴击概率、暴击倍率、是否受幸运影响、是否能对 Boss 生效,都要有明确规则。随机暴击会增加波动,适合装备构筑;如果游戏强调精确动作,暴击过高可能破坏可读性。

暴击结果要有反馈:数字颜色、音效、特效。不要让玩家无法分辨普通伤害和暴击。

状态效果

燃烧、中毒、流血、减速、易伤都属于状态效果。状态效果要通过同一系统结算,不要每个效果自己改血量。

状态字段:

字段说明
effect_id稳定 ID
duration持续时间
tick_interval跳伤间隔
stack_rule刷新、叠层、独立
source来源

叠层规则尤其重要。中毒是刷新持续时间,还是叠加层数?燃烧能不能同时存在多个来源?不写清楚会很难平衡。

反馈和浮字

伤害结果应该生成反馈数据,而不是 UI 自己猜:

damage_result amount=24 type=fire critical=false shield_break=true killed=false

UI 根据结果显示浮字、颜色、护盾破裂图标。音效和 VFX 也从结果判断。这样反馈和实际结算一致。

浮字不要太多。多段伤害可以合并或降低显示频率,否则战斗画面会被数字覆盖。

战斗日志

内部战斗日志对调试非常有用:

damage source=player_sword target=robot base=20 crit=1.0 armor=0.8 final=16 shield=0 hp=44

玩家反馈“这个敌人怎么一刀秒我”时,开发者能看伤害来源、倍率和最终值。发行版可以只在详细日志模式记录,避免日志过大。

QA 清单

测试检查
普通命中血量扣除正确
无敌帧不受伤
格挡减伤或免伤
护盾破裂溢出和反馈正确
抗性不同类型倍率正确
暴击概率和反馈
状态跳伤间隔、叠层、死亡
低帧率多段伤害不重复

补丁调参

伤害系统补丁要小心。改一个全局倍率会影响所有武器、敌人和难度。建议优先定位具体问题:某敌人抗性太高,某状态叠层失控,某武器暴击倍率过高。补丁说明也要具体。

保留一组标准战斗测试:普通敌人、护盾敌人、Boss、陷阱、状态效果。每次伤害管线改动都跑一遍。

最终检查清单

  • 所有伤害通过统一事件进入管线。
  • 结算顺序固定并文档化。
  • 伤害类型数量可控,抗性可解释。
  • 护盾、生命、溢出和破盾规则清楚。
  • 暴击和状态效果有稳定规则。
  • UI、音效、VFX 使用伤害结果,不重复计算。
  • 内部战斗日志能追踪基础值到最终值。
  • 补丁调参用标准战斗场景回归。

伤害系统是战斗可信度的核心。个人 Steam 游戏只要让每一次伤害都能解释,玩家就更容易接受失败,开发者也更容易平衡和修 bug。

伤害预览和玩家理解

如果游戏有装备或技能选择,伤害结果要能被玩家理解。属性面板可以显示基础伤害、伤害类型、暴击率、状态效果。不要把所有公式暴露出来,但要让玩家知道为什么某武器适合打护盾,某技能适合打群怪。

对于策略或回合制游戏,可以提供伤害预览:预计造成多少伤害、是否破盾、是否击杀。动作游戏则更适合通过图鉴、训练场和反馈表现,让玩家逐步理解。

友军伤害和来源归属

是否有友军伤害要提前定义。玩家技能能否打到召唤物,敌人是否会误伤队友,陷阱击杀算谁的,都影响成就、奖励和任务。伤害事件里的 sourceowner 要分清:陷阱本身是 source,触发陷阱的玩家可能是 owner。

来源归属不清,会导致击杀统计、经验、掉落和成就错乱。每种特殊伤害都要在测试表中覆盖。

多段伤害和重复命中

持续火焰、旋转刀刃、毒雾这类多段伤害要有命中间隔和同一目标冷却。否则低帧率或碰撞重复进入时,可能一秒内结算太多次。伤害管线应支持 hit_cooldown_per_target,并在日志中记录跳过原因。

多段伤害的 UI 也要克制。每一跳都显示大数字会遮挡画面,可以合并小数字或降低显示频率。

标准化测试敌人

建议做几个内部测试靶:无抗性、护盾、火焰弱点、毒免疫、高护甲。每次改伤害公式都用同一组技能打靶,确认结果符合预期。这比在真实关卡里靠感觉测试更稳定。

难度倍率放在哪里

难度倍率应在伤害管线的固定位置应用。比如先计算攻击、暴击、抗性,再应用难度倍率;或难度只影响敌人对玩家的最终伤害。不要让武器脚本、敌人脚本和关卡脚本各自乘一次难度,否则结果很难解释。

难度说明也要和实际一致。如果简单难度只降低玩家受到的伤害,就不要写“敌人更少”。玩家对难度选项的理解会影响反馈质量。

环境伤害和陷阱

环境伤害也要走同一管线,但可以使用特殊来源。岩浆、尖刺、坠落、毒雾都有不同规则:是否受护甲影响,是否能暴击,是否触发受击硬直,是否会击杀。规则写清后,玩家不会觉得同样是火焰,有的扣护盾有的不扣很奇怪。

陷阱伤害还要考虑任务和成就。敌人被陷阱击杀,奖励算不算玩家的?如果陷阱是玩家触发的,归属可能不同。

调试显示最终公式

内部构建可以在命中时显示详细公式:基础伤害、暴击倍率、抗性、护盾吸收、最终伤害。这个显示只给开发者看,但对平衡很有帮助。看到公式后,很多“伤害不对”的问题会变成某个倍率重复应用。

补丁前后对比

修改伤害管线前,保留一份标准输出表。补丁后用同样攻击打同样测试靶,对比差异。如果差异超出预期,说明改动影响范围更大。伤害系统是共享底层,任何改动都要有对照。

继续阅读

探索更多技术文章

浏览归档,发现更多关于系统设计、工具链和工程实践的内容。

全部文章 返回首页