Lua/Love2D不同文件夹同名类require缓存冲突最优解决方案咨询
Lua/Love2D 多游戏整合同名模块冲突解决方案
问题核心来源于Lua的
require函数机制:所有通过require加载的模块都会被缓存到package.loaded表中,相同模块名(require的入参)只会被加载一次。你目前的写法应该是在两个游戏中都直接调用require("Ball"),且通过动态修改package.path的方式匹配对应游戏的目录,因此第一次加载Game1时package.loaded.Ball被赋值为Game1的Ball类,加载Game2时因为package.loaded.Ball已存在,即使搜索路径变更也不会重新加载,最终出现类覆盖问题。
方案评估
- 方案1:重命名Ball.lua
可以解决问题,但可维护性差,后续新增游戏如果出现重名文件还要反复改名,不推荐。 - 方案2:用
dofile加载Ball文件
可以解决问题。dofile不走模块缓存,每次调用都会读取并执行对应路径的文件,你只要在游戏加载时传入正确的Ball.lua文件路径即可:
注意如果单局游戏内需要多次用到Ball类,只需在游戏初始化时调用一次-- Game1 加载逻辑 local Ball = dofile("games/game1/Ball.lua") -- Game2 加载逻辑 local Ball = dofile("games/game2/Ball.lua")dofile存为局部变量即可,避免重复加载浪费性能。 - 方案3:提前require后传参
也可以解决问题,只要你require时带上游戏目录作为命名空间,两个Ball模块就不会出现缓存冲突:
该方案性能最优,所有模块仅加载一次,但需要修改游戏的初始化逻辑接收外部传入的类。-- 主菜单预加载逻辑 local Game1Ball = require("games.game1.Ball") local Game2Ball = require("games.game2.Ball") -- 启动对应游戏时传入对应Ball类 startGame1(Game1Ball) startGame2(Game2Ball)
最优推荐方案
比上述三个方案更符合Lua模块规范的解法是直接调整各游戏内的require路径,加上游戏目录作为命名空间,不需要修改文件名、不需要换加载函数、也不需要额外传参:
-- Game1 内的Ball加载代码 local Ball = require("game1.Ball") -- Game2 内的Ball加载代码 local Ball = require("game2.Ball")
两个模块在缓存表中的key分别为game1.Ball和game2.Ball,完全不会冲突,同时可以正常利用require的缓存机制,无需额外处理。
如果你不想修改原游戏内的require("Ball")写法,可以在每次退出游戏返回主菜单时,手动清空对应模块的缓存:
package.loaded.Ball = nil
下次进入游戏时require就会重新加载当前搜索路径下的Ball文件,也可以快速解决问题。
内容的提问来源于stack exchange,提问作者Cédric Bélanger-St-Pierre
相关产品推荐
相关产品推荐

