Function from ScriptA got called by ScriptB Accidentally

I have a main.script with:

function on_message(self, message_id, message, sender)
	if message_id == hash("startgame") then
		on_startgame()
	end
end

function on_startgame()
	msg.post("main#main", hash("reset_score"))
	msg.post("canvas#home", "disable")
	msg.post("canvas#game", "enable")
	msg.post("canvas#result", "disable")
end

I also have a post_spawner.script within the same collection:

function on_startgame()
	is_game_running = true;
	time = go.get("#", "interval")
end

Some how, post_spawner.script’s on_startgame() gets called by main.script’s on_message(). Why is that? I thought the functions are contained within the script and Defold was designed to use Messaging System to keep things decoupled. I have check some sample projects and this is how they write their functions.

In Lua everything is global by default (end up in “_G” table) e.g.

function my_function() -- adds _G.my_function 
  my_var = 1 --adds _G.my_var
end

You have to specify local keyword to avoid it:

local function my_function()
  local my_var = 1
end
2 Likes

I see. So I made both main.script’s and post_spawner.script’s on_startgame() local:

local function on_startgame()

But this fails:

function on_message(self, message_id, message, sender)
	if message_id == hash("startgame") then
		on_startgame()
	end
end

ERROR:SCRIPT: main/post_spawner.script:39: attempt to call global ‘on_startgame’ (a nil value)
stack traceback:
main/post_spawner.script:39: in function <main/post_spawner.script:37>

The only solution I did to fix this is to move my local function above the on_message(). Is this how you normally do things here in Defold? How do commercial / decent-sized game setup their scripts? I’m coming from Unity C# with years of exp and I’m trying to learn the “right” / “scalable” way of development in Defold.

1 Like

Further info about Lua:

1 Like

Yes, Lua requires forward declaration, the function should be declared above its call.
You can avoid it putting function into a table (local table or a lua module).

1 Like

Yes, you should use local functions an order them so that they are defined before they are used. For complex cases where that does not work, you should either:

  • Use a Lua module and put functions that belong together into the module: https://defold.com/manuals/modules/
  • Create the local variable for a function before defining the function:
local my_function

local function example(x)
    my_function(x)
end

my_function = function(x)
    print(x)
end

example(3)
2 Likes

C and C++ the compilers require forward declaration. In Lua a name will return nil (-> false) if it has not been assigned (yet); that is code needs to have been parsed by the interpreter before it can be run, aka forward references/declarations. This means that you can write some really dodgy code if you use global variables.

1 Like