Can't get collision detection to work

Godot Version

4.2

Question

I’m creating a 2D chain reaction game. I have two-pronged “sprockets” laid out in a grid, and when one is clicked, it should rotate 90 degrees, and if it collides with another sprocket, then that sprocket should rotate, collide with others, and so on. The problem is, when a sprocket rotates, there is no collision detection, even though their CollisionShape2Ds end up overlapping.

The sprockets are all duplicates of a scene and set up as:

RigidBody2D
– Sprite2D
– CollisionShape2D

The RigidBody2D has both layer and mask set to “1”.

I have an “_on_body_entered” signal connected to the “_on_body_entered” function.

Here is my code. Any help would be greatly appreciated. And if you need more info from me, just let me know.

Thanks.

extends RigidBody2D

var target_rotation: float = 0
var rotation_increment: float = 90
var lerp_speed: float = 5
var is_rotating: bool = false

@onready var sprite = $Image

func _ready():
	set_process_input(true)

func _process(delta):
	if is_rotating:
		rotation_degrees = lerp(rotation_degrees, target_rotation, lerp_speed * delta)
		if abs(rotation_degrees - target_rotation) < 0.1:
			rotation_degrees = target_rotation
			is_rotating = false

func _input(event):
	if event is InputEventMouseButton and event.pressed:
		if event.button_index == MOUSE_BUTTON_LEFT:
			var local_mouse_position = sprite.to_local(event.position)
			var bounding_box = Rect2(Vector2(), sprite.texture.get_size())
			if bounding_box.has_point(local_mouse_position):
				target_rotation += rotation_increment
				is_rotating = true

func _on_body_entered(body):
	if body is RigidBody2D and body != self:
		print("Collision detected with another sprocket")
		var other_sprocket = body as RigidBody2D
		other_sprocket.propagate_rotation(rotation_increment)

func propagate_rotation(rot_value: float):
	var new_target_rotation = rotation_degrees + rot_value
	if new_target_rotation >= 360:
		new_target_rotation -= 360

	target_rotation = new_target_rotation
	is_rotating = true

did you try just print(body) at the first line of func _on_body_entered(body)?
any output?

1 Like

If all bodies are Layer 1, Mask 1, they should should collide but not overlap, as they are colliding with each other’s company boundaries, same way a player body landing on a platform would not overlap the platform’s collision box. You said they do overlap, but I still think the problem lies in that collision setup.

1 Like

There are a few things that can cause problems there.

First, just covering the basics.
Check if you are getting the _on_body_entered callback called. A very common mistake is not increasing the “Max contact points” from 0, and activating “Contact Monitor” inside the Solver zone of the rigidbody2D.
Without this, there will be no body_entered signals emitted.

Second:

This can cause a LOT of problems. Specially when dealing with rigidbodies.
Always prefer to use _physics_process to move/rotate things when possible.

But the real problem is that you are changing the rotation of the rigidbody.
Doing so will break the physics.
Always move rigidbodies with apply_force and apply_torque inside process functions, or else you’ll be overriding the physics and make a chain of things break.

If you must manually change the rotation or position, then you must do so inside a special function named “_integrate_forces”, within the state variable.

Not sure if that is your specific problem. But it is very likely affecting you somehow.

2 Likes

Thanks for the help, guys. I’ll go over it today and see if I can get it to work.

Please be aware, that changing the physics state should rather be done in _physics_process() and not in _process().

See here: Godot notifications — Godot Engine (stable) documentation in English

1 Like

Should I not be using a RigidBody2D for the sprockets?

I know a little Python, and I’ve been using Godot for about a week, so this is all still a bit new to me.

you mean like just use area2d?

Demo: physics_tests

Perhaps this official demo will help you decide which nodes and settings are best and perhaps develop new creative ideas. :slight_smile:

image

1 Like

Thanks, I’ll check it out.