活动期的掉率要翻倍、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 实战帖,语法、参数与示例一篇讲透。进入文章地图 · 查看全部 →
设计初衷 行会招人的门槛是双刃剑:无门槛的行会人满为患却乌合之众,高门槛的行会精英云集却关死了普通玩家的归属感。分层准入的目…
设计初衷 副本钥匙是副本经济的闸门:钥匙太贱,副本门口排大队、产出洪水冲垮经济;钥匙太贵,副本冷清、核心玩法没人体验。密钥平…
设计初衷 节日活动是在线峰值的引爆点:春节回城烟花一放,比奇主城同屏人数冲上日常的三倍,卡顿、掉线、排队接踵而至。峰值预案的…
底层原理 单线程的 Lua 没有并发,却有"重入":玩家的一次操作还没走完,同一次点击的第二个触发又进来了(双击、连点、宏)…
底层原理 一条业务链路往往穿越四五个函数:入口触发 → 校验 → 结算 → 通知。玩家对象、来源渠道、事务单号这些"全程都要…
业务场景 拜师系统的人数规则:一师最多三徒,出师空位才可再收。申请侧痛点:师父一次收到十几份申请无从挑起,口头答应后被人抢先…