活动期的掉率要翻倍、BOSS 的血量要回调、补偿要立刻发——这些改动等不了下一次停服。配置热更新让数值的调整在线上滚动生效:文件一改、几十秒后全服生效,运营的手感与玩家的体验同频。
---定时器扫描配置文件的修改时间
setontimerex(82, 15)
function HotCfg.tick()
for name, path in pairs(HotCfg.paths) do
local mtime = HotCfg.mtimeOf(path)
if mtime ~= HotCfg.loadedAt[name] then
local ok, tbl = HotCfg.load(path)
if ok then
HotCfg.tables[name] = tbl
HotCfg.loadedAt[name] = mtime
Ops.log("热更生效: " .. name)
else
Ops.alert("热更失败(格式错): " .. name)
end
end
end
end
定时器每 15 秒扫一轮配置文件的修改时间,mtime 变化即重载:加载成功替换内存表并记录时间戳,加载失败告警且保留旧表——坏的配置文件在半路被拦,线上跑着的永远是上一份完好的配置。生效的窗口 15 到 30 秒,运营改完掉率去打一只祖玛教主验证,反馈的回路比发版快一百倍。
---业务读表:永远走代理入口
HotCfg.tables = { drop = {}, mon = {}, shop = {} }
function HotCfg.get(name)
return HotCfg.tables[name]
end
---掉落结算:每次读表拿到最新值
function Drop.roll(monName)
local tbl = HotCfg.get("drop")
local cfg = tbl[monName]
if not cfg then return nil end
for _, d in ipairs(cfg.items) do
if math.random(1, 10000) <= d.rate then
return d.item
end
end
return nil
end
生效的语义靠读的纪律:业务代码不缓存配置表的引用,每次结算走 HotCfg.get 的代理入口——热更换的是 tables 里的表,持有旧引用的代码读不到新值,这是热更失效的头号原因。引用的替换是原子的(整表换新),读侧不会见到半新半旧的配置。热更的边界同样要立规矩:结构性的变更(加字段、改格式)不走热更,热更只承诺值的调整,结构与值的分界写进配置文档。每次热更留痕:谁改的、改了哪个表、生效时刻,配置的变更史与版本库同步归档。
热更的生效延迟监控,从文件落盘到内存替换的耗时分布;配置的读侧扫描,缓存旧引用的代码在评审与静态检查双重拦截。
业务曾经缓存了掉率表的局部引用,热更后全服还是旧掉率,排查两小时定位到引用缓存,代理入口的规范执行。mtime 的秒级精度曾经让一分钟内的两次修改只生效一次,内容哈希的比对辅助判断。热更的失败曾经静默,运营以为改了实际没生效,失败的告警与生效的日志双通道。
热更的白名单只含数值表,逻辑表(触发、脚本)的变更走发布流程。热更的权限收敛到运营主管,变更的审计按人归档。活动期的配置变更提前公告,玩家对数值变化的知情权是信任的一部分。
本文由 996 技术组基于 996 引擎官方知识库与浮生梦老师课程体系整理。团队长期从事传奇类引擎 Lua 后端逻辑、客户端界面与商业版本交付,内容以官方知识库与真实项目为出处,按版本持续修订。
全站技术干货持续更新:996 引擎 / Lua 实战帖,语法、参数与示例一篇讲透。进入文章地图 · 查看全部 →
实战应用:用在哪里 沙巴克占领行会坐收税收却只进不出,非占领行会的玩家心里不平衡。税务官玩法把税收做成明账:占领行会对摆摊与…
实战应用:用在哪里 高端玩家婚姻系统只有仪式没有过程,社交绑定缺一个高光事件。比武招亲做成擂台玩法:擂主设擂摆彩头,攻擂者报…
实战应用:用在哪里 开服七日限时礼包发到第六天断了粮,9 月 1 日当天领奖按钮灰的,投诉当天破千。事故根因是一条数字日期循…
实战应用:用在哪里 玩家拔线不退游戏,连接半开着,人不在指令也没有,在线数虚高,容量预案被假数据带着跑。心跳探测给每个在线玩…
实战应用:用在哪里 周三发了合成系统补丁,周四又改强化概率,两条变更叠加后玩家分不清是哪个改出来的。发布日历把全月变更集中排…
实战应用:用在哪里 容量预案需要知道滚动一小时的副本进入峰值,而不是全天累计。滑动窗口用 60 个槽位每槽记一分钟的进入数,…