Message sent twice (SOLVED)

Hi guys! I am completely newb to coding generally and Lua in particular and now I have a problem which I couldn’t resolve. Hope somebody can help me with my code. So, here we go…

I have some problem with message passing. I have a ‘reactor’ object that receives message when user clicks it and upgrades it state (changing sprite to the next one). But reactor upgrades two times as needed, i.e. variable state = state + 2 except of state = state + 1 (i’ve checked it with debugging). I think it somehow connected to message passing, maybe script sends/recieves messages two times or something.

Sending object:

function on_input(self, action_id, action)

		--some code

		-- if click/touch
		-- and the cursor has collided with something
		-- then send a message to script of collided object
		if self.pressed and self.collision_id then
			self.activeObjectHash = self.collision_id .. "#scr_reactor"
			self.activeObjectHash = self.activeObjectHash:gsub('[%[, %]]','')
			msg.post(self.activeObjectHash, "upgrade")
		end

Receiving object:

function on_message(self, message_id, message, sender)
	if message_id == hash("upgrade") and money > 0 then
		self.state = self.state + 1
		msg.post("#spr_reactor", "play_animation", {id = hash(self.state)})
		money = money - 1
	end
end

Thanks!

self.collision_id - what is it? If it collision reacts - I think collision work 2 times and because it send 2 messages

self.pressed - action.pressed need use and need use action_id configurated in Input folder game.input_bindings

For example from my proj - if action.pressed and action_id == hash(“reload_pressed”) then

self.collision_id = message.other_id so it’s just an object with which cursor is collided

Here is a full code of sending object (based on https://github.com/britzl/publicexamples/tree/master/examples/click_and_drag):

function init(self)
	msg.post(".", "acquire_input_focus")
	msg.post("#collisionobject", "disable")
	self.collision_id = nil
	self.pressed = false
end

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

function update(self, dt)
	msg.post("@render:", "clear_color", { color = vmath.vector4(95 /256, 129 / 256, 161 / 256, 1 ) })
	self.collision_id = nil
end

function on_message(self, message_id, message, sender)
	if message_id == hash("collision_response") then
		if not self.collision_id or go.get_position(self.collision_id).z < message.other_position.z then
			self.collision_id = message.other_id
		end	
	end
end

function on_input(self, action_id, action)
	if not action_id or action_id == hash("LMB") then
		local action_pos = vmath.vector3(action.x, action.y, 0)
		
		-- update cursor position
		go.set_position(action_pos)
		
		-- keep track of click/touch state
		if action.pressed then
			msg.post("#collisionobject", "enable")
			self.pressed = true
		elseif action.released then
			msg.post("#collisionobject", "disable")
			self.pressed = false
		end
		
		-- if click/touch
		-- and the cursor has collided with something
		-- then send a message to script of collided object
		if self.pressed and self.collision_id then
			msg.post("@render:", "draw_text", {text = "Collision object: " .. self.collision_id, position = vmath.vector3(50, 60, 0)})
			self.activeObjectHash = self.collision_id .. "#scr_reactor"
			self.activeObjectHash = self.activeObjectHash:gsub('[%[, %]]','')
			msg.post("@render:", "draw_text", {text = "Collision object's script: " .. self.activeObjectHash, position = vmath.vector3(20, 30, 0)})
			msg.post(self.activeObjectHash, "upgrade")
		end
	end
end

If I right readed your code, then user where not release LBM you will receive messages from collision object. Try disable collision object in on message block after found first collision.

I mean:

if message_id == hash("collision_response") then
		if not self.collision_id or go.get_position(self.collision_id).z < message.other_position.z then
			self.collision_id = message.other_id
 msg.post("#collisionobject", "disable")
		end	
	end

Second thought - move all code after – if click/touch to on_message function.
I mean

function on_message(self, message_id, message, sender)
	if message_id == hash("collision_response") then
		if not self.collision_id or go.get_position(self.collision_id).z < message.other_position.z then
			self.collision_id = message.other_id
 msg.post("@render:", "draw_text", {text = "Collision object: " .. self.collision_id, position = vmath.vector3(50, 60, 0)})
			self.activeObjectHash = self.collision_id .. "#scr_reactor"
			self.activeObjectHash = self.activeObjectHash:gsub('[%[, %]]','')
			msg.post("@render:", "draw_text", {text = "Collision object's script: " .. self.activeObjectHash, position = vmath.vector3(20, 30, 0)})
			msg.post(self.activeObjectHash, "upgrade")
		end	
	end

Because you detect collision after user press button garantee(enable collision)

1 Like

Thanks, I’ll try it.

One more thing I’ve observed. It happens only if I have more than one object I want to click on. If I have only one reactor - everything’s fine. But if I have 2, it works this way as described. If 3 reactors, then state = state + 3 i.e. state = state + amount of reactors.

Reactors have same collisionId?

Try enable physics debug and see what happened - msg.post("@system:", “toggle_physics_debug”)

Yes, collision id is the same.

May be you need make unique state for each object? I right understand you have self.state = self.state + 1 and same script fro all reactors GO?

Yes, the same script. But I send message only to the defined scripts with this approach:

			self.activeObjectHash = self.collision_id .. "#scr_reactor"
			self.activeObjectHash = self.activeObjectHash:gsub('[%[, %]]','')
			msg.post(self.activeObjectHash, "upgrade")

for example, it will be msg.post(‘reactor#scr_reactor’, “upgrade”)

Hmm. Really I think problem with not correct disabled collision object. I think need debug physics for more understanding problem

Hm, doesn’t work. Where I need to paste it?

This works! Thanks, man!

I usually place it code on main script. on_init function

To be able to use it, one needs to enable it in game.project.

P.S. Hm, I found another strange thing :smiley: If one hits space, it will add 1 money (implemented for testing). But, actually it addes 2. Lol, wtf :smiley: Ah, nevermind, I got it why.

May be same error.