• Godot Help
  • Alternative to using both PhysicsBody2D AND Area2D in the same player scene

Hey all! To preface, I'm a huge fan of keeping things modular. What this means for me, in the case of a player scene, is that I'd like to structure things as follows:

  1. The root node is of type CharacterBody2D. The attached script only deals with player movement (or perhaps even just wiring up child nodes, if I decide to make the movement functionality itself a child node in the future).
  2. Now, suppose we have collectibles with their own Area2D nodes. In order to pick these up, the player requires a node with a custom script - let's call it Collector - that masks collisions on the collectible layer and deals with picking them up.

I want to design it this way in the interest of modularity. This way, being a player doesn't necessarily imply you can pick things up - the Collector node does.

Now, here's where my problem comes into play. Originally, I was hoping to just grab a reference to the CharacterBody2D from the Collector script and hook into some sort of collision signal. However, unlike with Area2D, which has signals like AreaEntered and BodyEntered, CharacterBody2D has no such thing. I understand why this is the case, but if possible, I'd like to avoid defining an Area2D with the exact same collision shape as the player's bounding box just for the purpose of detecting collectibles, as this seems wasteful.

Also, I should mention that my reasoning for not doing things the other way around (i.e. having collectibles check for the player on BodyEntered) is twofold:

  1. That would be a LOT of extra logic running when there are dozens or even hundreds of collectibles lying around, and only one or a few players.
  2. On collision, I wouldn't be able to check if the colliding body is of type Collector, because the type would instead be that of the top-level script. And again, being a player doesn't necessarily imply that they can collect things.

Sorry for the mouthful. Any insight here would be greatly appreciated!

Could you check the collisions from CharacterBody2D then notify the object if it can be collected?
Something like this from the Godot Docs:

Using move_and_collide.
var collision = move_and_collide(velocity * delta)
if collision:
print("I collided with ", collision.get_collider().name)

Using move_and_slide.
move_and_slide()
for i in get_slide_collision_count():
var collision = get_slide_collision(i)
print("I collided with ", collision.