Check Collision with Spawned Collection Child Object

As part of my Defold journey, I try to make a Flappy Bird clone. I’m spawning 2 post (like pipes) game objects (upper and lower). They are both under a parent named pair. pair is the only game object of a collection file.

My main character, a cat, detects the collisions:

function on_message(self, message_id, message, sender)
	if message_id == hash("collision_response") then
		local parent = go.get_parent(message.other_id)
		if message.other_id == hash("/roof") then
			hit_roof(message, self)
		elseif message.other_id == hash("/water") then
			gameover(self)
		elseif message.other_id == hash("/collection0/upper") then
			gameover(self)
		end
	end
end

Initially I coded:

elseif message.other_id == hash("/upper") then

but doesn’t work. Then I coded:

elseif message.other_id == hash("/collection0/upper") then

It worked but only for the first post. Succeeding posts have the /collection1..2..3..etc.

Here’s how I spawn the posts:

local function spawn(self)
	local y_min = 568 - 225
	local y_max = 568 + 225
	local y_random = math.random(y_min, y_max)
	local p = vmath.vector3(770, y_random, 1.1)
	local g = collectionfactory.create("#factory", p)
	local pair_id = g[hash("/pair")]
	table.insert(self.spawned_posts, pair_id)
	msg.post(pair_id, "register", { spawner = go.get_id() })
	
	print("spawned posts: " .. #self.spawned_posts)
end

Here’s how the collection file looks like:

And here’s the main collection:

In summary, how do I correctly check whether the cat collided with any of the spawned posts (since each spawn gives the id prefix /collectionN?

You can simply create a game object. Add 2 sprite components to it (up and down pipes), add a collision object. On it, add 2 box shapes and place them on the sprites respectively. Now, both pipes will work with the same id since they have the same GO as their parent.

If you want to use your current setting, do not put the / at the beginning of an id (when you put / at the beginning, it will look for the object under the same collection even though it has its own vollection.) Use:

elseif message.other_id == hash("upper") then
elseif message.other_id == hash("lower") then
end
1 Like

I would also recommend this approach.

I can also mention that it is not recommended to have collision objects (at least not dynamic ones) as child objects since the physics engine will compete with the game engine about which transform to use. But I assume that your objects are kinematic so my comment doesn’t really apply in this case.

2 Likes

Yes, they are Kinematic. So bottom line, my mistake here was the use of /? and it should have been:

elseif message.other_id == hash("upper") then
    gameover(self)
end

Right? But it still doesn’t go inside this clause. Here’s the variable values:

I instead approached it using collision Groups and Masks. If any reader is interested about this project I do to learn Defold (and please let me know if this is prohibited here):

1 Like

As you can see in your screenshot the id of the other game object is “/collection0/upper”. Since you are comparing two hashes they need to be the same:

elseif message.other_id == hash("/collision0/upper") then
    gameover(self)
end

But it would honestly make a lot more sense to check if other_group is of a specific type. I see that you have not assigned any groups to your collision objects (they are all default). I would configure your collision objects like this:

  • The collision object on your Flappy Bird to have group: bird and mask: pipe
  • The collision objects on your pipes to have group: pipe and mask: bird

And then in the collision check on your bird script:

if message.other_group == hash("pipe") then
    gameover(self)
end

Documentation about groups and masks:

1 Like