沙巴克战况榜每 5 秒重绘一次,旧版每次重绘都为 10 个行会按钮新建闭包注册点击,一场城战打完客户端内存涨了 40MB 不回落。病灶在循环里创建的闭包长期持有旧榜单数据,监听不释放,GC 收不走。处理思路是把数据更新与监听绑定拆开:数据每帧换新,绑定一次成型。
旧写法在重绘循环里为每个按钮包一个闭包,闭包把整张旧榜单捕获进去;榜单越大、重绘越多,泄漏越快。修正为面板创建时一次性绑定,点击时读模块级最新数据,闭包数量从每帧十个降到全局十个。
local rankData = {}
local function makeHandler(idx)
return function()
local d = rankData[idx]
if d then
SL:ShowSystemTips(d.gn .. " 当前积分 " .. d.score)
end
end
end
local function buildRow(x, y, idx)
local b = GUI:Button_Create(panel, "RankBtn" .. idx, x, y, "ui/rankbtn")
GUI:addOnClickEvent(b, makeHandler(idx))
end
定位靠内存采样:collectgarbage("count") 在十次重绘前后各采一次,增量稳定为正就是泄漏。修复后再挂一个 300 秒心跳,增量超过 8MB 自动提示重载界面。
local baseMem = collectgarbage("count")
local ticker = SL:Schedule(function()
local now = collectgarbage("count")
if now - baseMem > 8192 then
SL:ShowSystemTips("界面内存异常增长,建议重开战况榜")
baseMem = now
end
end, 300)
十次重绘为一组,对比修复前后每组的内存增量,修复后增量应归零;点击十个行会按钮核对明细与当前榜单一致;界面关闭后确认 SL:UnSchedule 已注销心跳,进程内定时器计数归零。监控上线后客户端内存曲线与 GC 峰值。低配真机单独跑一轮,采样抖动下告警阈值不误报才放量。
只修闭包不修心跳,重绘泄漏停了,心跳还在后台空转,界面关闭后定时器仍存活,SL:UnSchedule 必须在销毁钩子里成对调用。每帧重建 rankData 表是另一个隐藏负担,改成复用表只改字段后 GC 压力下降一半。低配机型上 collectgarbage("count") 采样有抖动,告警阈值给到 8MB 而不是 2MB,误报率才压下来。按钮在重绘时销毁重建的方案也测过,控件反复创建析构的代价比闭包更大,最终选择固定控件只换数据。按钮坐标写死后分辨率适配出错位,坐标改由布局表驱动才治好。
全站技术干货持续更新:996 引擎 / Lua 实战帖,语法、参数与示例一篇讲透。进入文章地图 · 查看全部 →
实战应用:用在哪里 装备回收商 NPC 每天按评分收购玩家的装备,裁决之杖、骨玉权杖按攻击、持久加权打分,榜上只要前五名。数…
实战应用:用在哪里 沙巴克攻城是全服行会战的最高舞台:攻方砸开城门、抢占皇宫,守方依托城墙与复活点反打。规则设计的关键是节奏…
实战应用:用在哪里 影分身玩法给法师职业补上生存短板:危急时刻召唤四个影分身分担仇恨,敌人需要在六格范围内分辨真身,猜错就浪…
实战应用:用在哪里 组队邀请、行会宣战这类关键信令丢了没有兜底,玩家只能反复手点,高峰期体验很差。重试机制给信令加确认回执:…
实战应用:用在哪里 新资料片上线首日预约量常是日常十倍,一口气全开会让数据库与登录网关同时过载。滚动开区把开区动作排成队列:…
实战应用:用在哪里 百人同屏的沙巴克外围战场,每个玩家每秒跑动会触发数次位置更新,全部即时下发时广播量随人数平方增长,网关先…