Passing messages containing a table between collections

Hello,
i am having some trouble passing messages that contains a table between 2 scripts in my game. When the player object dies, it passes the message “dead” to the score script, which then should pass the score to an endscreen script, however i am receiving this error:
Could not send message ‘scorePass’ from ‘loader:/go#loader’ to ‘endscreen:/go#endscreen’.
stack traceback:
[C]:-1: in function post

Initially i thought this was because the score script was no longer loaded as collections had been switched, but i tried not unloading the collection which did not help.
Any help with this would be greatly appreciated


Screenshot 2023-03-31 001512

You missed enclosing “scorePass” inside brackets.

if message_id == hash("scorePass") then

Skipping the parentheses on a function call with a single argument is actually ok!

@Tang please check the url. Add a print(msg.url()) to the init function of the receiving script and confirm that it is indeed “endscreen:/go#endscreen”

Yep, the location is correct, but i am now receiving these errors, the “test” print shows that the if statement in the score script.

Hmm, can you please share score.gui_script here? Please share as text!

Wasn’t sure if you wanted just the receiving code - here is the whole script :slight_smile:

    function init(self)
    	self.maxHealth = 100
    	print(msg.url())
    	self.score = 0
    	maxHealth = gui.get_node("full")
    	threequartHealth = gui.get_node("75")
    	halfHealth = gui.get_node("50")
    	quartHealth = gui.get_node("25")
    	

    end
    function update(self, dt)
    	--
    end
    function on_message(self, message_id, message, sender)
    	if message_id == hash("add_score") then                 -- [2]
    		self.score = self.score + message.score             -- [3]
    		local scorenode = gui.get_node("score")             -- [4]
    		gui.set_text(scorenode, "SCORE: " .. self.score)    -- [5]
    	end 

    	if message_id == hash("hit") then
    		--healthScale.x = healthScale.x - 0.3
    		--gui.set_scale(green, healthScale)
    		playerhealth = healthPass[1]
    		
    		if playerhealth < 100 and playerhealth > 75 then
    			gui.set_alpha(threequartHealth, 1)
    			gui.set_alpha(maxHealth, 0)
    			--if healthpass[1] = 50

    		elseif playerhealth < 75 and playerhealth > 50 then
    			gui.set_alpha(halfHealth, 1)
    			gui.set_alpha(threequartHealth, 0)

    		elseif playerhealth < 50 and playerhealth > 0 then
    			gui.set_alpha(halfHealth, 0)
    			gui.set_alpha(quartHealth, 1)
    		end
    	end

    	if message_id == hash("dead") then 
    		print("test")
    		--msg.post("loader:/go#loader", "preloadEndscreen")
    		scoreTable = {score}
    		msg.post("endscreen:/go#endscreen", hash("scorePass"), scoreTable)

    	end

    	if message_id == hash("usernameSend") then
    		usernamePass[1] = "currentUsername"
    		local highscoresFile = io.open("highscores.csv","a+")
    		usernameString = currentUsername, self.score
    		highscoresFile:write(usernameString)
    		highscoresFile:close()
    	end
    end

Hmm, that looks ok. So there’s something not quite right in “endscreen:/go#endscreen”. Are you sure it is loaded and that the URL is correct?

If possible, zip your project and share it here.

im not 100% sure the endscreen collection is loaded, is there any way to check? will zip it in a moment

The project is too large to be able to send, is there any specific parts you need to see?

Why don’t you put a print() in the relevant script? That will let you know if it’s loaded.

1 Like

E.g. a print(msg.url()) will show you 1) that it’s loaded, and 2) what the actual url is.

1 Like

just tried this - printed a message url in both the score script and the endgame script init functions, score is loaded directly after the menus and the endgame opens directly after the main collection(which contains the score script), which i think means that the message cant be sent because they aren’t open at the same time?

here is a link to a cloud sharing site i uploaded the project onto:
https://share.internxt.com/d/sh/folder/49d970d5d2bc4a97ead2/c7d44988658172936af2e15d637b0f061e8c2ab1551129dd889ed3a10ffa119e

I’m unable to download the project, I get a message saying “Shared files no longer available”.

Try zipping your project again, this time excluding the .internal folder and the build folder. That should make the project small enough to share. You can also try emailing me at bjorn@defold.se.

hi, ill try emailing it to you, i removed the build folder but could not find an .internal folder?
once again, thanks for all the help :slight_smile:

hi,
Should have sent an email

Thanks. I’ve received the project. The problem was indeed that the endscreen wasn’t loaded when you tried to send the message. This is what your code looked like:

local function load_endscreen(self)
	msg.post("go#endscreen", "load")
	msg.post("go#endscreen", "enable")
end

function on_message(self, message_id, message, sender)
    if message_id == hash("scorePass") then
		load_endscreen(self)
		msg.post("endscreen:/go#endscreen", hash("scorePass"), scoreTable)
		unload_endscreen(self)
    end
end

The call to msg.post("go#endscreen", "load") will send a message to load the endscreen BUT since msg.post() is an asynchronous operation it means that it won’t complete immediately. Your code will continue to execute and you will send an “enable” message (also async) and then you will immediately proceed to also send a “scorePass” message.

The next things that happens is that the engine will process the messages in order:

  1. “load”
  2. “enable”
  3. “scorePass”

The problem here is that you have not given the loaded collection and the game objects and components inside time to initialize. Your “enable” message will most likely be ignored and your “scorePass” message will not be able to reach “endscreen:/go#endscreen” since the components haven’t been initialized.

What you need to do is to wait until you receive a “proxy_loaded” message before you proceed to send the “scorePass” message.

You read more about loading collection proxies in the manual: