Misunderstanding about Physics and _on_body_entered

Godot Version

v4.2.1 Stable-Official

Preface

I have some experience with Unity 2D - Brand new to GoDot- I am in no way saying that to insinuate that GoDot should be intuitive based on that. Just illustrating that I am new to this engine.

Question

I have a 2D scene with a tilemap that is set up with collision mapped to layer 1.

I have a Bee (RigidBody2D) with a CollisionPolygon2D (see image below), in the parameters of this bee contact monitor is enabled and max contacts reporting is set to 500

I also have a player, characterbody2D with a collisionshape2D and a rigidbody2D with the same parameters of reporting, and max contacts reporting is the same.

I would like to get a notification in my GDScript of the bee when the bee has come in contact with either a player or a plant

To help accomplish that, I have a method in the rigidBody2D node on the bee I pulled from the Node inspector named _on_body_entered(body) that I expected to inform me when a player walks into the bee.

func _on_body_entered(body):
print(body.Name)

Currently, when the application is started – none of this happens. I get no notifications in the console.

I also attempted to ignore the variable _body in the function and did a print(“something touched the bee”) with no luck. Nothing in the console.

Please help me understand what is happening here - I really like GoDot so far I am just stuck on this particular issue.

Thank you

Honestly, I think your best bet is to do the tutorials starting with First 2d Game - Godot Tutorials It will give you a good grounding with the engine and remove any preconceptions carried over from using Unity (I did the same). Sorry to not be more helpful, but after doing them I think it will make a lot more sense to you.

1 Like

Just made a test project with rigidbody (RB) + characterbody (CB) config and it seems the event doesn’t fire because when CB collides with RB, as RB is a RIGID body, the CB simply pushes RB around and never “enters” it.

“body_entered” is a signal that comes from CollisionShape. If you had attached the collision shape to an Area2D, for example, which doesn’t have physics/rigidity, then indeed when a body (character, rigid, etc.) enters that collision shape, the event “body_entered” is emitted. However, in your case, since bee is a rigid body, it can only be pushed around and never entered.

To detect a collision between CharacterBody with a RigidBody, you have 2 options:

  1. Easy/beginner: add an Area2D object called, say, HitBox to your Player object. That Area2D will have own collision shape that’s perhaps slightly bigger than player’s collision shape. Then in your bee script you can listen to area_entered signal and if it’s player’s area, inflict dmg.
  2. Hard/advanced: do it all in code. Use move_and_collide() to move the player. That func returns an object that has info about any collisions happen.

You can google “HitBox HurtBox” for some tutorials of this concept.

Finally, to @octopuddle’s point above: I, too, would recommend some solid tutorial that covers all the basics and the best one I’ve found so far is this: https://www.youtube.com/watch?v=nAh_Kx5Zh5Q

Cheers!

3 Likes

CharacterBody and Rigidbody don’t directly interact as you would expect.

Like previously said, CharacterBodies don’t have the _body_entered callbacks and it feels very ugly to check for collision.
Like this, in the _process function:

# move_and_slides moves the entity, but also returns true if there were collisions
if move_and_slide():
		# Collided with something
		for i in range(get_slide_collision_count()):
			if get_slide_collision(i).get_collider() is RigidBody3D:
				print("Collided with rigidbody")

I’d said sometimes its just easier to use Rigidbody for the player too.

CharacterBodies are not that bad, they are there to give you a lot of freedom on how you movement occurs and reacts. But that also means that are a lot of manual setup you need to do to make things work.