Message passing and addressing (SOLVED)

Hi,
First off – thanks for making this – defold is wonderful.

I am making a game with platforms that characters jump on, and after a time, the platforms disappear. When they run out of time the platform broadcasts a “platform_disabled” message to a game logic script letting it know:

if self.time_to_live==0 then
	msg.post(".", "disable")
	msg.post("/game_logic", "platform_disabled",{platform_id = go.get_id()})
end

The game logic script which responds to a “platform_disabled” message from the platform itself and then sends out another “platform_disabled” message to the characters.

The central game logic script knows which characters are in the world because it dynamically spawns them and retains a reference to them like so:

self.a_character_id = factory.create("#character_factory", etc..)

Then it tries to re-broadcast the message like so:

msg.post(self.a_character_id, "platform_disabled",{platform_id = message.platform_id})

The character script receives the message, but oddly the game logic script also receives the message.

Since the game logic script receives it’s own message, this ends up creating a ton of messages. The game logic script posts the message again, and again, etc, rather than just positing it once.

When I changed the message name to “a_platform_disabled” only the character script got the message, like so
msg.post(self.a_character_id, "a_platform_disabled",{platform_id = message.platform_id})

My question is, am I addressing the instances incorrectly, or is there a better way to do it? Or should I be trying to use unique message names in general just to be safe?

Thanks again for making this wonderful engine!

Alex

2 Likes

My guess is that this is a case of the url being nil, which will cause the msg.post() to post a message to itself.

print() self.a_character_id and any other ids or urls you use in your msg.post() calls and make sure they aren’t nil (unless it’s on purpose ofc).

You could do something like this early on in your code (init function of some script):

local msg_post = msg.post
msg.post = function(url, ...)
	if not url then
		print("WARNING! url is nil, is this intended?", debug.traceback())
	end
	msg_post(url, ...)
end

This will inject some code into the msg.post function and print a warning and a stack trace if a url is nil.

3 Likes

Thanks so much for writing back.

The a_character_id is

hash: [/instance13]

But I’m not sure if that qualifies as a URL.

Is the instance id enough of a URL or do I need to be more specific somehow?

Thanks.

The instance id should be fine. My concern was if the parameter was nil. If you modify my code snippet and print all calls to msg.post then you should see from where all of them originates and you should be able to track down why there is a call to the game logic itself.

Is it possible that the two scripts in question belong to the same spawned game object? Addressing the message to the game object, rather than the specific script component, triggers a broadcast which sends the message to every component, thereby the two scripts, if this is the case.

1 Like

@britzl – your guess was right :slight_smile:

I had a few different characters managed by the game logic script and had not initialized one of them to reduce noise via debugging. The game logic script still posted to that character’s instance id, which since it hadn’t been initialized was nil. This caused the loop.

As long as all of the instance ids for characters that the game logic script post to are not nil, it is working fine.

Thanks @Ragnar_Svensson as well for your suggestion. There is a game object that owns the factory that is used to spawn the character instances, and messages are sent to those instances.

Cheers,
Alex

2 Likes