Collisions are triggering on a) layers an area is not masked for and b) seemingly based on velocity

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By jame

I am following along with this tutorial, and have hit a bug that I am having difficulty understanding. I’ve created an enemy slime character, and am adding a hurtbox on top for when the playable character jumps on it. However, the enemies squashed themselves for no apparent reason. Using print statements, I saw that they were actually squashing themselves. Not understanding how this works, I slowed down the game speed using Engine.time_scale to see how this was happening frame-by-frame. At very slow speeds, the self-squash didn’t happen, but when one of the slimes picked up more speed it squashed itself.

I have no clue why this is happening. I’ve set the collision layer of both the hurtbox and the “floor checking” collision box to the same value, which I’ve named “enemy”. But I’ve turned off the “enemy” collision mask on the hurtbox. If I turn off the “enemy” collision layer on the hurtbox, then everything works as expected. How is it able to collide with itself, even with “enemy” not selected as a collision mask? And why is this seemingly affected by the speed at which the enemies move?

I know this is a bit complicated, so I’ve uploaded a couple of short videos to demonstrate what I mean.

pt 1
pt 2

Please provide full source code of your project, without it it is very hard to find physics-related bugs or issues, because there are plenty of reasons why it might not work in a way you expect.

AlexTheRegent | 2022-06-23 08:23

Hi Alex! What’s the best way to share the full source code? Should I push the project to my Github so you can clone it?

jame | 2022-06-23 16:58

You can upload it to github or to cloud like google drive or dropbox.

AlexTheRegent | 2022-06-23 18:40

Apologies for the delay, repo is uploaded here

jame | 2022-06-26 14:38

:bust_in_silhouette: Reply From: AlexTheRegent

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")

    print(name + " squashed by:")