[SOLVED] Does not detect trigger_response or other_id of collision object

So I’m reading Collision messages in Defold and am trying to implement it.



Inside of the script of the same game object that has the collision:

function on_message(self, message_id, message, sender)
	if message_id ==hash("is_book_in_slot") then
		if message_id == hash("trigger_response") and message.other_id == hash("/book_slot_go#book_slot_collision_object") then
			msg.post("/minigame_go#shelving", "shelved_book_in_correct_slot")
		else
			msg.post("/minigame_go#shelving", "shelved_book_didn't_slot_in")
		end
	end
end

The script that send messages to it and is part of minigame_go:

function init(self)
	msg.post(".", "acquire_input_focus")
	go.animate("/book_going_into_slot_go", "position.x", go.PLAYBACK_LOOP_PINGPONG, 600, 1, 2)
	timer.delay(8, false, function()
		print("Failed.")
		msg.post("main:/main#main", "game_over")
	end)
end

function final(self)
end

function on_input(self, action_id, action)
	if action_id == hash("space") then
		msg.post("/book_going_into_slot_go#book_going_into_slot", "is_book_in_slot")
	end
end

function on_message(self, message_id, message, sender)
	if message_id == hash("shelved_book_in_correct_slot") then
		print("Success.")
		msg.post("main:/main#main", "game_over")
	elseif message_id==hash("shelved_book_didn't_slot_in") then
		print("Failed.")
		msg.post("main:/main#main", "game_over")
	end
end


I’m confused, from reading the documentation, I would’ve thought that since my book and slot collision objects are both triggers, it should register a trigger response, and I think I got the message id correct? Thanks in advance.

In the above snippet of code you are first checking if message_id is “is_book_in_slot” and on the next line you check if the message_id is “trigger_response”.

The message_id (or any other variable) will not change value you like that from one line to another.

Could you please explain what you attempted to do with those two lines of code and maybe someone can suggest an improvement?

No problem, I should’ve been clearer from the beginning, that probably explains the issue. So what I’m trying to do is check whether the book lands inside the slot only when you press down the spacebar. Book’s on left, slot’s the orange.
image

So that’s why originally I had a script that handled the input, i.e. if action_id == hash("space"), then I was planning on passing that message to the script that’s part of the book object (which also has the collision object) and check to see if it has collided with the slot.

Ok, but do you understand what I tried to explain with message_id not being able to be two different things at the same time? If you need to check for both a “is_book_in_slot” message and a “trigger_response” message then you need to track them one by one and set a flag when they are true. Something like this:

function on_message(self, message_id, message, sender)
	if message_id ==hash("is_book_in_slot") then
		self.is_book_in_slot = true
		-- question is when this value should be set to false again?
		-- When "space" is released?
	end

	if self.is_book_in_slot and message_id == hash("trigger_response") and message.other_id == hash("/book_slot_go#book_slot_collision_object") then
		msg.post("/minigame_go#shelving", "shelved_book_in_correct_slot")
	else
		msg.post("/minigame_go#shelving", "shelved_book_didn't_slot_in")
	end
end

Oh I see, no I wasn’t understanding that, that was my bad then. Yes I think so, when space is released is when the is_book_in_slot should be false. I was using is_book_in_slot just so I can call the script that the game object that has the collision object. I just want to check if two game objects, slot and book are overlapping only when I’m pressing down the spacebar. I hope I’m making sense?

Like what I was thinking for the logic was:

  1. Press space bar
  2. Check if the book and slot are overlapping
  3. If book and slot are overlapping, print out true then go back to the main collection (still trying to figure out the collection proxies)
  4. If book and slot aren’t overlapping when I press space bar, print out false then go back to the main collection

Store this in a variable where you set the value to true when action.pressed is received in on_input(). Set the value to false when action.released is received in on_input(). This kind of variable is often called a flag. You raise the flag (set value to true) when the condition is met (space is pressed) and you lower the flag (set value to false) when the condition is no longer met (space is released).

You can keep track of this when you receive a trigger_response where message.enter is true. If message.enter changes to false they are no longer overlapping.

Use the combination of the two flags above to achieve what you need!

1 Like

Oh I think I see the issue, I’m confused on how I would do this in two scripts.

script that handles input, so this is where I’d be making the flag, but the question is how would I expose the flag to the other script?

I did read Message passing in Defold so I know you could pass it via message paramter, but like you said message_id can’t be two different things at the same time, so I don’t think I can pass the flag that way like the way I have it below. Am I correct in assuming that on_input runs based on tick, so it would be checking every frame? Would exposing the flag as a global variable be a good idea though, because of scope safety, I think that’s what it’s called. I’m really debating whether I should have this be one script instead of two. I don’t think I can decouple these two scripts so might as well merge them into one.

function on_input(self, action_id, action)
	if action_id == hash("space")  and action.pressed then
		msg.post("/book_going_into_slot_go#book_going_into_slot", "is_book_in_slot", {self.action_to_check_is_book_in_slot == true})
	elseif action_id == hash("space")  and action.released then
		msg.post("/book_going_into_slot_go#book_going_into_slot", "is_book_in_slot", {self.action_to_check_is_book_in_slot == false})
	end
end

So this is the script that handles the collision object, book_going_into_slot.

function on_message(self, message_id, message, sender)
	if message_id ==hash("is_book_in_slot") then
// make a new variable that gets the value of the old variable, should update based on input
		self.check_is_book_in_slot =  message.action_to_check_is_book_in_slot
	end
	if self.check_is_book_in_slot and message_id == hash("trigger_response") and message.enter and message.other_id == hash("/book_slot_go#book_slot_collision_object") then
		msg.post("/minigame_go#shelving", "shelved_book_in_correct_slot")
	else
		msg.post("/minigame_go#shelving", "shelved_book_didn't_slot_in")
	end
end

Ah I see, I’m debugging this, I don’t think I’d be setting the flag on release, I just want the check to occur when the player has pressed spacebar once and that’s it. If the book doesn’t overlap the slot, then the game’s over.

But why do you need two scripts? Can’t you use a single script? Using two scripts for such a simple thing smells a bit of object oriented thinking, which typically leads to code spread out all over the place…

Yea now that I think about it, it’s unnecessary I’m just going to use a single script, that makes sense, hahahaha, it’s because I’m more used to using languages that are OOP (i.e. Java, C#), and I’ve used Unreal (C++) and Unity in the past (more Unreal though) so yea, that probably explains everything doesn’t it.

Ok then, I’m rewriting this to just have one script, this is now attached to the book_going_into_slot_go and I debugged it, the input works but it’s not getting to the on_message part even though it is entering the slot. Hm.

function init(self)
	msg.post(".", "acquire_input_focus")
	go.animate("/book_going_into_slot_go", "position.x", go.PLAYBACK_LOOP_PINGPONG, 600, 1, 2)
	timer.delay(8, false, function()
		print("Failed.")
		msg.post("main:/main#main", "game_over")
	end)
end

function final(self)
end

function on_input(self, action_id, action)
	if action_id == hash("space")  and action.pressed then
		self.is_book_in_slot = true
	elseif action_id == hash("space")  and action.released then
		self.is_book_in_slot = false
	end
end

function on_message(self, message_id, message, sender)
	if self.is_book_in_slot and message_id == hash("trigger_response") and message.enter and message.other_id == hash("/book_slot_go#book_slot_collision_object") then
		print("Success.")
		msg.post("main:/main#main", "game_over")
	else
		print("Failed.")
		msg.post("main:/main#main", "game_over")
	end
end

Are you getting the “trigger_response” message? Depending on where you moved your code you may have moved everything to the script which didn’t have a collision object?

I put the new code inside of shelving
image
so it should notice there is a collision object, unless I’m not doing it correctly.

Enable physics debugging and check that everything still looks ok.

You can also share your project as a zip file here so that we can take a look.

I did and it looks like they’re overlapping, Upload files for free - #IGM.zip - ufile.io, unfortunately it’s still too big even zipped, so my bad for that, the collection is shelving
image
Thank you, I appreciate it.

I took a look at your project and you have not set up your collision objects correctly. One is assigned group “book” and the other “book_slot” BUT both of them have the mask set to “default”. The “book” group needs to have mask “book_slot” and vice versa!

Please read the documentation here: Collision groups in Defold

2 Likes

Thank you so much for spotting that. I managed to fix that and rewrote that on_message if statement.

if self.is_book_in_slot then
		if message_id == hash("trigger_response") --[[message.other_id == hash("/book_slot_go#book_slot_collision_object") ]] then
			if message.enter then 
				print("Success.")
				msg.post("main:/main#main", "game_over")
			else
				print("Failed.")
				msg.post("main:/main#main", "game_over")
			end
		end
	end