Signal not triggered on collision between a RigidBody2D and a CharacterBody2D

Godot Version

4.2.2

Question

I’m trying to create a falling platform.
I was wondering with type of node to use.
I tried to use a RigidBody2D (layer 1, mask 2) for the platform because I saw it has a body_entered signal.
I set lock_rotation to true and gravity scale to 0 on the platform with the idea of putting it back at 1 after a shaking animation to make it fall.
I also set contact_monitor = true and the max_contacts_reported = 1 in the inspector of the Platform.

EDIT: I saw on the documentation of the RigidBody2D that if contact_monitor and max_contacts_reported to at least 1 the RigidBody2D should however emit an event when it collides with something but I cannot make it work…

EDIT2: I seems like the contact_monitor works only if the RigidBody2D comes into contact with another RigidBody2D, but it’s ignoring the CharacterBody2D

The problem is that the player is a CharacterBody2D (layer 2 mask 1) and the platform doesn’t trigger the on_body_enter signal so it can know that the Player is on it.
(I connected the signal on the platform scene)

I would like to detect the collision on the platform script and not from the player script.

Thanks for your help.

Greetings @Naga :slight_smile:

I built a 2D clone of what you described and so far it’s working as expected.

Did you attach CollisionShape2D to your RigidBody2D and your CharacterBody2D as well as setting it to some nice shape?

Often users move the collision shapes by accident in the 2D view - and not the whole object - are you sure your colliders are congruent with your visible shapes?

How are you moving your CharacterBody2D? I am using “move_and_slide()” in my example.

Hi! Thanks for the reply!

Both the Player and the Platform have a CollisionShape2D: a circle for the player and a rectangle for the platform.

The shapes appear to be correct because the player can land on the platform.

The script of the player is the default one with just some modifications to change the actions and to flip the Sprite2D (maybe i can mention that I followed the Brackeys tutorial and I’m trying to add some things to get familiar with Godot).

I also tried to enable the property contact_monitor on the Platform setting a positive value for the ‘Max Contacts Reported’ property, but nothing changed.

This is the player script for completeness:

Player Script
func _physics_process(delta):
	# Add the gravity.
	if not is_on_floor():
		velocity.y += gravity * delta

	# Handle jump.
	if Input.is_action_just_pressed("jump") and is_on_floor():
		velocity.y = JUMP_VELOCITY

	# Get the input direction and handle the movement/deceleration.
	# As good practice, you should replace UI actions with custom gameplay actions.
	var direction = Input.get_axis("move_left", "move_right")
	if(direction > 0):
		animated_sprite_2d.flip_h = false
	elif(direction < 0):
		animated_sprite_2d.flip_h = true
	
	if !is_on_floor():
		animated_sprite_2d.play("jump")	
	elif(direction == 0):
		animated_sprite_2d.play("idle")
	else:
		animated_sprite_2d.play("run")
	
		
	if direction:
		velocity.x = direction * SPEED
	else:
		velocity.x = move_toward(velocity.x, 0, SPEED)

	move_and_slide()

Ah i see, the signal is not triggering thats the problem you want to solve?
Then ‘signal trigger’ is defenitely a keyword you should use in the title i recommend.

I know this problem for a long time - and it’s a pain - but i am not skilled enough to explain why this happens. Good luck with it!

Edit: i would add an Area2D node with a collision shape to detect body collision events.

PS: if you set gravity to -1 and let the RigidBody2D crashes on its way upwards into the CharacterBody2D, it triggers the signal for me. This doesn’t help but it’s a strange observation.

Yes that’s my problem. I updated the title thanks.

Using the Area2D was one of my attempts, but I found out that if the shape of the Area2D is the same as the one of the RigidBody2D the signal is still not triggered; I needed to make the Area2D collider a little bit higher than the RigidBody2D collider to make the signal emit.
But thanks to this post I thought again about it. I think that the signal on_body_entered does exactly what his name indicates: the Player collider should enter the other collider (in both cases: if the other is a RigidBody2D or an Area2D).
The physics engine is basically blocking this: it correctly makes the Player not enter the RigidBody2D. Thats also why I needed to make the Area2D a little bit higher with respect to the RigidBody2D collider!

When you put the gravity scale to -1 the platform rapidly goes up, and the collision detection is not fast enough to prevent the Player from entering the Platform; so for a brief moment the two colliders are one inside the other and the signal on_body_entered is triggered.

So now I need to think about other ways to detect if the two objects are ‘touching’.

EDIT: I saw on the documentation of the RigidBody2D that if contact_monitor and max_contacts_reported to at least 1 the RigidBody2D should however emit an event when it collides with something but i cannot make it work…

Thanks again!