Functions of the same name across multiple scripts acting oddly (SOLVED)

I’ve got a collection which contains 3 game objects representing a grid.

  • Manager object
    – manager.script
  • Gfx object
    – gfx.script
  • Grid object
    – grid.script

The manager issues messages telling the grid what it should do, the gfx object handles the cell visuals, the grid object handles the actual cell data.

I needed to control when they were initialized, so I gave both gfx.script and grid.script a function named ‘initialize’, but when I get a message to both objects, the initialize function in grid.script is called twice and the one in gfx.script is skipped over.

A print statement in both scripts on_message function confirms they are both receiving the correct message, but a call to initialize(self) from inside gfx.script results in grid.script’s initialize function being called. If I do nothing else but rename the functions, (to init_gfx and init_grid respectively) it works.

Is this a quirk to lua that I’m not aware of?

Thanks guys!

edit: code
(manager)

function init(self)
    -- send an init message to our grid gfx object
    msg.post("p_grd_gfx#gfx", "initialize")
    -- let our grid selector know which object is our player (target)
    msg.post("p_grd_selector#selector", "initialize", { target_id = "" })
end

(gfx)

function on_message(self, message_id, message, sender)
	print("gfx rcv msg: " .. tostring(message_id) .. " : " .. tostring(message) .. " : " .. tostring(sender))
	if message_id == hash("initialize") then
		initialize(self)
	end
end

-- in future change this to initialize and have it trigger a cool animation
function initialize(self)
    -- Add initialization code here
    -- Remove this function if not needed
    print("initializing p_grid_gfx")
    -- spawn our grid graphics
    local cell_size = self.cell_size
    local x_off = self.offset_x - (cell_size)
    local y_off = self.offset_y - (cell_size)
    for y = 0, self.grid_y-1, 1 do
    	for x = 0, self.grid_x-1, 1 do
    		local px = (x*cell_size) + x_off
    		local py = (y*cell_size) + y_off
    		local position = vmath.vector3(px, py, 0)
	    	cells[x+(y*self.grid_x)] = factory.create("#cell_fact", position, nil, {})
	    end
    end 
end

(grid)

function initialize(self, target)
    print("initializing p_grd_selector")
    msg.post(".", "acquire_input_focus")
    self.target_go_id = target
end

function final(self)
    msg.post(".", "release_input_focus")
end

function on_message(self, message_id, message, sender)
	-- rcv initialize from manager: call initialise(self, target)
	print("selector rcv msg: " .. tostring(message_id) .. " : " .. tostring(message))
	if message_id == hash("initialize") then
		initialize(self, message.target_id)
	end
end
1 Like

You are declaring initialize() as a global variable. This means that it will be globally available from all script files and module, and if more than one script or module declares the initialize() function they will overwrite each other. You should always prefix your functions with the local keyword to make them local to the script in which they are declared.

2 Likes

Oh, wow, thanks!

You guys are amazingly helpful.

2 Likes

There’s detailed information about this in our scripting manual: http://www.defold.com/manuals/lua/#_locals_globals_and_lexical_scoping

And in the Programming in Lua book: https://www.lua.org/pil/4.2.html

2 Likes