伤害公式的每一步除法都会产生小数:取整的方向(向下、四舍五入)决定 1000 次攻击后玩家实际多打或少打多少血。取整的取舍不是代码风格问题,是数值精度的问题——漂移的累计能改写平衡表。
---伤害公式的三处取整点
function Damage.calc(atk, def, multiplier)
-- 第一处:防御减免的取整,向下保护攻击方
local reduced = math.floor(atk * (1 - def / (def + 500)))
-- 第二处:倍率加成,四舍五入保持期望
local boosted = math.floor(reduced * multiplier + 0.5)
-- 第三处:随机浮动,向下取保底
local final = math.max(1, math.floor(boosted *
(0.9 + math.random() * 0.2)))
return final
end
三处取整点各有立场:防御减免向下取整保护攻击方的期望、倍率加成四舍五入维持设计的中值、随机浮动向下取整保证最低伤害的口径。三个方向不统一的后果是漂移:全部向下取整的公式让玩家的实际输出比设计值低 3% 到 5%,万分比的差距在排行榜上是一个身位。漂移的度量用期望对比:公式的理论期望与十万次模拟的实测均值比对,偏差超 1% 即取整方向的策略需要复核。
---百分比的整数化:万分比避免浮点
function Damage.pct(base, permille)
-- 万分比整数乘除,全程无浮点
return math.floor(base * permille / 10000)
end
---累计加成的守恒:分步取整改为末次取整
-- 危险:每一步取整,误差逐步累计
-- local a = math.floor(base * 1.1)
-- local b = math.floor(a * 1.2)
-- 改造:末次统一取整
local function calcFinal(base)
return math.floor(base * 1.1 * 1.2)
end
精度的守恒两条纪律:百分比全程用万分比整数运算(浮点的 0.1 加 0.2 不等于 0.3 在伤害里是实打实的血量);分步取整改末次取整——每步 floor 一次的累计向下偏差在多段加成的公式里放大明显,中间保留小数、只在最终结算时取整,数值的期望与设计对齐。浮动区间的下限保护:伤害的保底 1 点让防御方的极端堆叠不至于百分百免疫,取整与保底共同定义伤害的下边界。期望的验证进数值的验收流程:每个版本的伤害公式跑十万次模拟,期望值与设计值的对齐是版本上线前的必答题。
伤害期望的模拟测试进每日构建,期望漂移超 1% 即阻断发布;玩家实测与设计期望的偏差监控,论坛的数据帖是免费的验证集群。
全部向下取整曾经让烈火剑法的实际伤害比面板低 4%,论坛的算术帖炸版,取整方向按立场分置后修复。浮点的累加曾经用于连击的加成,0.1 的精度噪声让万次连击统计偏差可观测,万分比整数化替换。保底曾经设 0,极端防御的互殴打出零伤死循环,保底 1 点终结。
取整的策略写进数值文档:每处取整的方向与理由,公式的维护者读得懂前辈的立场。模拟测试的种子固定,漂移的对比有可复现的基准。数值的调整走热更时同步跑一次模拟,调整的副作用当场可见。
本文由 996 技术组基于 996 引擎官方知识库与浮生梦老师课程体系整理。团队长期从事传奇类引擎 Lua 后端逻辑、客户端界面与商业版本交付,内容以官方知识库与真实项目为出处,按版本持续修订。
全站技术干货持续更新:996 引擎 / Lua 实战帖,语法、参数与示例一篇讲透。进入文章地图 · 查看全部 →
实战应用:用在哪里 付费玩家的付费点集中在商城,成长线里缺一个长期投入的钩子。成长基金让玩家在低等级时一次性买入,随等级提升…
实战应用:用在哪里 行会联赛打得不热闹,观战人数不到参赛人数的一半。联赛竞猜给观战者一张入场券:用竞猜币押注胜负,赔率随投注…
实战应用:用在哪里 七夕限时活动原计划七天,上线第二天下午整点活动面板突然关闭,奖励领了一半,玩家以为被砍了福利,两小时内工…
实战应用:用在哪里 HTTPS 证书过期一次,全服登录白屏了半个多小时,值班才发现证书没人管。证书续期机制把到期日写进系统变…
实战应用:用在哪里 从行会面板点进成员列表再点开个人名片,连按返回键直接退回了主城,中间两层界面全部跳过。界面堆栈管理用一张…
实战应用:用在哪里 限时商城的稀缺商品上架即被抢,玩家错过窗口感觉被区别对待。商城橱窗把每件限时商品的下架时间做成可视化倒计…