生命周期?内存崩溃有解!
昨天 15:3517 浏览综合
生命周期审计结果 & 整改方案 审计概况 扫描 20 个 Lua 文件,发现 11 个问题(3 高 / 5 中 / 3 低),10 个模块无问题。 高危问题(3 项) # 模块 问题
1 main.lua:159-160 SubscribeToEvent("Update"/"KeyDown") 永不退订,全局每帧跑
2 main.lua 全局 13 个 Create*Screen 函数,零个 Destroy/Cleanup
3 AudioManager.lua:42-57 Init() 创建 9 个引擎 C++ 节点(1BGM+8SFX),无销毁逻辑,如重复调用会泄漏引擎对象
中危问题(5 项)
# 模块 问题
4 * main.lua:74-134 15+ 模块级变量跨画面不重置(isArenaBattle_、arenaWaves_ 等脏数据风险)
5 BattleManager 战斗实例含定时器,结束后仅 currentBattle_=nil,无显式清理
6 InventoryUI:17 lastTapInfo_ 表每次单击增条目,永不清除
7 NurtureUI:34 rebuildCallback_ 闭包赋值后从不置 nil,持有外部引用
8 JobChangeUI:298-301 M.branches_、M.buildBranchCard_ 挂在模块表上从不清理
低危问题(3 项)
HandleUpdate 非战斗帧空跑(开销极小)、BattleUI callbacks 引用链、ArenaData/SocialData 模块缓存(有自限机制)。
整改方案(4 步)
步骤 1:main.lua 引入统一画面切换函数
在 main.lua 中新增 SwitchScreen(newState, createFn) 函数,所有画面切换统一走这个入口:
lua
复制
local function SwitchScreen(newState, createFn, ...)
-- 1) 调用离开清理:根据旧 currentState_ 清理对应模块
local old = currentState_
if old == GameState.BATTLE then
if currentBattle_ then BattleManager.Cleanup(currentBattle_) end
currentBattle_ = nil
battleEndTimer_ = 0
battleEndResult_ = nil
end
if old == GameState.ARENA then
isArenaBattle_ = false
arenaOpponentInfo_ = nil
arenaWaves_ = nil
arenaStatMult_ = nil
end
-- 通知可清理的 UI 模块
if NurtureUI.Teardown then NurtureUI.Teardown() end
if JobChangeUI.Teardown then JobChangeUI.Teardown() end
if InventoryUI.Teardown then InventoryUI.Teardown() end
-- 2) 切换状态
currentState_ = newState
-- 3) 创建新画面
createFn(...)
end
然后把现有的 currentState_ = GameState.XXX + CreateXxxScreen() 调用全部替换为 SwitchScreen(GameState.XXX, CreateXxxScreen)。
步骤 2:为有状态的 UI 模块加 Teardown()
NurtureUI.lua:
lua
复制
function M.Teardown()
rebuildCallback_ = nil
end
JobChangeUI.lua:
lua
复制
function M.Teardown()
M.selectedIndex_ = nil
M.buildBranchCard_ = nil
M.branches_ = nil
M.baseClassId_ = nil
end
InventoryUI.lua:
lua
复制
function M.Teardown()
lastTapInfo_ = {}
end
步骤 3:AudioManager 防重入 + Shutdown
lua
复制
function M.Init(scene)
if bgmNode_ then return end -- 防重入
-- ... 现有创建逻辑 ...
end
function M.Shutdown()
if bgmNode_ then bgmNode_:Remove(); bgmNode_ = nil end
bgmSource_ = nil; currentBGM_ = nil
for _, n in ipairs(sfxNodes_) do n.node:Remove() end
sfxNodes_ = {}
end
步骤 4:BattleManager 显式清理
lua
复制
function M.Cleanup(battle)
if not battle then return end
battle._callbacks = nil
battle.animTimer = 0
battle.actionAnim = nil
end
不改动的部分
SubscribeToEvent("Update") 保留全局订阅(单入口应用,退订无实际收益,守卫条件已有)
ArenaData/SocialData 缓存保留(有 TTL 自过期,数据量小)
10 个无状态纯渲染模块不动
我相信很多人也碰到 这个问题了发出来给大家看看!然后去研究下!试过回来留言
来自TapTap[ID:27994320 瞎搞🦐卤虾]

