Handle collisions: Changing Area2D for CharacterBody2D ?

Godot Version

4.6

Question

Hello,

I try to make a 2D, where skeletons are chasing humans. When skeletons collide whith human, I want the human’s health to be reduced by the skeleton attack power each frame. I handle everything with Area2D, and it works perfectly. In the human script, I use get_overlapping_areas() and check for each if it’s a skeleton, and get his attack power to reduce the health.

But now, I want humans and skeletons to be blocked by walls if they collide, and I read that you can’t do that with Area2D. So I changed my Skeleton and my Human in CharacterBody2D instead of Area2D. But the behavior during collisions is changed now. And, I still want my skeletons to pass through humans, and deplete the health bar of the human. But if I’m using CharacterBody2D, skeletons are “blocked” by humans, or pushes humans, which is not what I want.

In short, I want my skeletons to pass through humans and empty their health bar, but I also want my skeletons (and humans) to be blocked by wall. Can I do that only with either Area2D or Charatcer2D, or am I forced to use both (CharacterBody2D for handling the collision with the walls, and Area2D for handling the damage to health bar) ?

Thank you in advance for those who will take time to answer.

To add a little bit of code, I used to do that when my humans where still Area2D, and I can’t anymore since they’re CharacterBody2D:

func _physics_process(delta: float) -> void:
	for area in get_overlapping_areas():
		if area is Skeleton:
			health_bar.apply_damage(area.attack_power * delta)

Don’t quote me if I’m wrong, but don’t the Collision Layers and Masks deal with all of that..? One may dictate which Layers interact with which Masks, so as to have different reactions depending on how they are set up. Have you looked at that aspect at all..?
It’s well explained here…
Godot Documentation : Physics Introduction …
Hope this helps.

You can give your CharacterBody2D an Area2D child (with the same collision shapes) and call $Area2D.get_overlapping_areas() from your script.

Best of both worlds.

Thank you for your answer, that’s exactly what I’ve ended up doing.

I have a CharacterBody2D to represent my Skeletons or Humans, so they can collide with walls. I disable collisions between them though (playing with collision masks and layers). Then I added an Area2D for humans called “hitbox”, so humans can take damage if a skeletons enters the hitbox.

Thank you for your answer.

I did use collision masks and layers, but that doesn’t fix my issue because if you have only CharacterBody2D and you disable collisions between them, the skeletons will never deal damage to humans because the collisions aren’t detected.

You can mark the answer as solution for other people with the same question.