_on_body_entered isn't being triggered by gentle collisions

Godot Version

4.2.2

Question

I’m making a little vegetable merge game. When two vegetables of the same type touch, they turn in to the next vegetable on the list.

GitHub
Itch

I have a Scene named Vegetable. It is a RigidBody2D with a Sprite2D and a CollisionShape.

My Vegetable has an _on_body_entered with some code to see if it is colliding with another vegetable of the same type. If it does, it deletes both vegetables and spawns the next vegetable between them.

This actually works perfect most of the time. But sometimes I have a situation where a vegetable is clearly touching another vegetable, but they rolled into each other and came to be touching at a low velocity and somehow _on_body_entered isn’t getting triggered.

I’ve gone so far as to switch the physics engine from Godot’s default to Box2D to see if that fixes it, but the issue persists.

Has anyone else seen a RigidBody come to rest on top of a RigidBody without _on_body_entered getting triggered? A vegetable can be resting on another vegetable of the same type and not merge, but a little boop with another vegetable will cause it to merge.

1 Like

has this happened for other fruits than the tomato? Considering you’ve switched physics engine I figure it must somehow be in the scripts.

Great question! I don’t think it’s vegetable-specific. Here it is happening with two carrots:

When I give those carrots a little nudge with an onion, they turn into a cucumber.

1 Like

Here are the two carrots merging into a cucumber, which merged with the cucumber below it to turn into a squash as expected:

1 Like

How many contact monitors are on for the vegetables?

There are 20 contact monitors on each vegetable.

Here are my settings on the base vegetable scene.

I guess the only thing I’d try left is using _integrate_forces instead of the body_entered signal.

func _integrate_forces(state: PhysicsDirectBodyState2D) -> void:
	var contact_index := state.get_contact_count()
	while contact_index > 0:
		contact_index -= 1
		var contact := state.get_contact_collider_object(i) as Vegetable
		if contact.species == self.species:
			# merge
			break

You’re terrible at explaining your set and scene. So, is there gravity. You’re making a challenger match game. Like Bejewled, or Candy Crush. You want to generate an economy falling from the top of the screen and a conversion system on the bottom. With fruits that collapse and merge. Is that right?

No dude. If you want to listen to the advise. You also have to apply the advise in the correct fashion. If you want to change the “contact monitor”. Less is more. Make it 1 contact monitor. That way the contact is counted 100% without a miss. And, always.

That sounds NSFW :rofl: