Search code examples
godotgodot4

CharacterBody3D.get_slide_collision() returning multiple collisions with same instance in the same position


I am working through the "Squash the Creeps" 3D game tutorial in Godot and I have found that when the player character uses the move_and_slide() method in order to initiate a landing movement on top of an enemy collision mesh that it sometimes increases the score by more than 1 even if landing on only a single enemy. It appears from the debugger that calling get_slide_collision_count() as suggested in the tutorial is indicating that there was more than one collision in some instances, and iterating over the indices of the collision array (KinematicCollision3D) shows that there are multiple collisions with the same colliding object (collision.get_collider()) at the same position (collision.get_position())

My questions is whether or not this is expected behavior? I can understand that the "move_and_slide()" method for character bodies is intended to be executed to take care of multiple subsequent collisions to ensure flush movement, but is it expected that it would lead to multiple reported collisions with the same object in the same single call to move_and_slide()?

If so, I would imagine it is standard practice when using the collisions reported by move_and_slide() that the developer programs around that and ensures that when iterating over the collisions that any subsequent collisions in the array with that instance are ignored?

If not, what am I doing wrong here to generate more than one collision with the same instance? It seems like this would be something that would be noticed by SOMEONE else who is running through this tutorial but a lot of searching has left me empty handed.

(Godot 4.1.1 btw)

The following is called in the _physics_process(delta) method:

for index in range(get_slide_collision_count()):
    var collision = get_slide_collision(index)
    var collider = collision.get_collider()
    var collision_position = collision.get_position()
    if (collider == null):
        continue
    if (collider.is_in_group("mob")):
        if Vector3.UP.dot(collision.get_normal()) > 0.1:
            collider.squash() # This increments the score
            target_velocity.y = bounce_impulse

collider.squash is being called sometimes 2-3 times instead of once even if only one enemy is squashed in terms of how many enemies the player is actually landing on. Debugger shows more than one collision with the same collider at the same collision_position in a single call to get_slide_collision(). I would expect every collision in the KinematicCollision3D object to be with a unique collider instance, not multiple times with the same object instance.


Solution

  • Yes, this is an expected behaviour.

    move_and_slide tries to slide the Character Body after the first collision until it reaches the required travel distance or causes a collision that cannot slide.

    Image showing a red circle object colliding with an irregular ground object, with multiple arrows showing the slide trajectory

    In this image the red circle is colliding twice with the blue ground object during move_and_slide, which will result in two different collisions between the same objects.