Lua跨文件访问全局变量 解决require循环加载报错问题
循环依赖报错原因
Lua的require机制会对正在加载的模块做标记,防止重复加载。你的代码执行链路为:
- main.lua启动加载,被标记为「加载中」
- main.lua执行到
require 'Bird',进入Bird.lua加载流程,Bird被标记为「加载中」 - Bird.lua执行到
require 'main',Lua检测到main正处于「加载中」状态,直接抛出loop or previous error loading module错误。
实际上你完全不需要在Bird.lua中反向引入main.lua:VIRTUAL_WIDTH和VIRTUAL_HEIGHT是没有加local修饰的全局变量,只要在Bird相关逻辑执行前完成赋值,就可以在Bird.lua中直接访问。
修复方案
方案1:调整加载顺序(最简单,适配现有代码逻辑)
只需要做两处修改:
- 删除Bird.lua中
require 'main'这行错误代码 - 把main.lua中的全局常量定义,移动到
require 'Bird'语句之前,保证加载Bird时依赖的全局变量已经完成初始化
修改后的main.lua关键代码:
push = require 'push' -- 优先定义全局配置常量 WINDOW_WIDTH = 1280 WINDOW_HEIGHT = 720 VIRTUAL_WIDTH = 512 VIRTUAL_HEIGHT = 288 -- 常量初始化完成后再加载依赖这些值的Bird模块 Bird = require 'Bird' local background = love.graphics.newImage('background.png') local backgroundScroll = 0 local BACKGROUND_SPEED = 30 local BACKGROUND_LOOP_POINT = 413 local ground = love.graphics.newImage('ground.png') local groundScroll = 0 local GROUND_SPEED = 70 ...
另外你的Bird.lua本身存在两个隐性bug,一并修正:o变量未加local会污染全局环境,x/y坐标赋值给类本身而非实例会导致所有Bird实例共享坐标值。修正后的Bird.lua完整代码:
local Bird = {} function Bird:new(name) -- 初始化实例表,加local避免污染全局 local o = {} setmetatable(o,self) self.__index = self o.name = name o.image = love.graphics.newImage('bird.png') o.width = o.image:getWidth() o.height = o.image:getHeight() -- 坐标绑定到当前实例,此时全局VIRTUAL_WIDTH/VIRTUAL_HEIGHT已经完成初始化 o.x = VIRTUAL_WIDTH / 2 - (o.width / 2) o.y = VIRTUAL_HEIGHT / 2 - (o.height / 2) return o end return Bird
方案2:传参初始化(耦合更低,推荐长期维护使用)
如果要避免跨文件依赖全局变量,可以把虚拟分辨率作为参数传入Bird的构造方法,彻底消除模块间的隐式依赖:
- 修改Bird.lua的new方法,增加分辨率入参:
function Bird:new(name, virtual_width, virtual_height) local o = {} setmetatable(o,self) self.__index = self o.name = name o.image = love.graphics.newImage('bird.png') o.width = o.image:getWidth() o.height = o.image:getHeight() o.x = virtual_width / 2 - (o.width / 2) o.y = virtual_height / 2 - (o.height / 2) return o end
- 在main.lua中实例化Bird时传入对应常量即可:
local player_bird = Bird:new('player', VIRTUAL_WIDTH, VIRTUAL_HEIGHT)
注意事项
不要为了图方便在模块中反向依赖入口文件,这种双向依赖会大幅提升代码耦合度,后续调整配置时很容易触发加载顺序、变量值为nil等难以排查的问题。
内容的提问来源于stack exchange,提问作者Dylariant
相关产品推荐
相关产品推荐

