Lua 的全局变量随手可写:G_oldPay = true 一敲就能跨模块通信,但全局的随手是架构的债——命名的冲突、状态的失控、热更的遗漏,全局变量的账单在项目变大后集中到期。
---失控的全局:谁都能改,改了没人知道
-- G_dropRate = 1.0 -- 三处代码各自赋值
-- G_bossAlive = false -- 五个模块同时读写
---受控的全局:注册制的命名空间
G = G or {}
function G.register(key, initial, readonly)
if G[key] ~= nil then
error("全局键冲突: " .. key, 2)
end
G[key] = { value = initial, ro = readonly or false }
end
function G.get(key)
local slot = G[key]
return slot and slot.value or nil
end
function G.set(key, value)
local slot = G[key]
if not slot then error("未注册的全局键: " .. key) end
if slot.ro then error("只读全局: " .. key) end
slot.value = value
end
受控的全局走注册制:每个键登记初始值与读写属性,键的冲突在注册当场报错——两个模块各自定义 G_dropRate 的惨案在注册的关口现形。只读的全局保护配置类的状态:引擎版本、开服时间这类只许装载器写、业务只读的值,写入的尝试当场炸出来。全局的清单自省:G 表的键集合就是全局状态的户口本,谁在户口上、谁黑户,pairs 一遍便知。
---全局改会话:状态挂到玩家域
---危险:全局记录玩家状态,多玩家互相覆盖
-- G_tradingWith = nil
---改造:状态进玩家的会话表
local Trading = { sessions = {} }
function Trading.start(actor, targetName)
Trading.sessions[actor] = targetName
end
function Trading.endOf(actor)
Trading.sessions[actor] = nil
end
全局的最优解是没有全局:玩家维度的状态(交易对象、临时 BUFF、任务进度)全部挂会话表,按玩家的键隔离——全局变量记录玩家状态的写法在两人同时交易时互相覆盖,会话化的改造是根治。真正值得全局的只有三类:进程级的配置、引擎的接口引用、跨模块的只读常量,三类的清单进架构文档。热更新的联动:全局的清点在热更时容易漏(模块的热重载不带全局),受控的全局在注册表的 reload 钩子里统一处理。
全局的裸写扫描:静态检查找 rawset(_G 与裸赋值的写法,未注册的全局键逐个清剿;G 表的键数与读写频次的统计,全局的膨胀有仪表可看。
两个模块的键冲突曾经只在特定加载顺序下爆,注册的顺序依赖让 Bug 飘忽,注册的声明式清单固定顺序。只读的全局曾经用 rawset 绕过,纪律的约束加代码评审的检查双保险。玩家状态的全局清退不干净,一半在会话表一半在全局,半吊子的状态迁移比不迁更难查。
全局的规范三句话进手册:注册制、会话化、只读保护。新模块的架构评审带全局清单的过目。全局键的命名带模块前缀,户口本的可读性是维护的速度。
本文由 996 技术组基于 996 引擎官方知识库与浮生梦老师课程体系整理。团队长期从事传奇类引擎 Lua 后端逻辑、客户端界面与商业版本交付,内容以官方知识库与真实项目为出处,按版本持续修订。
全站技术干货持续更新:996 引擎 / Lua 实战帖,语法、参数与示例一篇讲透。进入文章地图 · 查看全部 →
实战应用:用在哪里 明拍容易被大号威慑,普通玩家不敢出手。秘宝暗拍改为全服暗标:每周一件秘宝,玩家密价投标一次,截标前互相看…
实战应用:用在哪里 充值返利活动被风控规则误判成套利,480 个大额充值账号被批量封禁 24 小时,申诉两小时破千条。误封风…
实战应用:用在哪里 五人小队打沃玛教主,队友的血量状态只能靠点头像逐个看,集火转火慢半拍。小队血条在屏幕侧边紧凑排布四条队友…
实战应用:用在哪里 好友申请藏在好友面板的角标里,玩家半天不看一眼,申请积压让社交转化掉了一半。好友申请浮窗把新申请推到屏幕…
实战应用:用在哪里 矿洞产出人人有份等于人人不重视,矿位租赁把矿洞变成可经营资产:矿位按 24 小时租给个人或行会,产出归租…
实战应用:用在哪里 击杀 BOSS 后要同时做三件事:发奖励、记流水、刷新排行榜,全都写在 killmon 触发里互相拖累,…