You are correct, this is velocity-related issue. Let's take a look at your Enemy
class.
Your enemy has next mask layers: 1, 2, 5, 6. In other words, it looks for anything in these layers to trigger collision events. And your Enemy.top_checker
area located in layer 5. So, Enemy
class can register "self-hit" with own area. Despite the fact that Enemy.top_checker
is above Enemy
hitbox, Godot updates movement and areas with one-frame difference and looks like this is expected behavior. So, when moved distance between frames became higher than gap between Enemy
hitbox and Enemy.top_checker
hitbox, it will trigger collision with self.
Quickest way to fix your issue is to remove 5'th mask layer from Enemy. This way, enemy won't be able to hit themself and each other too. It you need to to handle collision between enemies, then you need to manually handle collision in signal. For example, here collision will exclude self-collision.
func _on_top_checker_body_entered(body):
if body == self:
# print("self squash is stopped")
return
$AnimatedSprite.play("squashed")
print(name + " squashed by:")
print(body.name)
print()