Search code examples
game-enginegame-developmentcollisiongodotgdscript

Collision of CharacterBody2D and StaticBody2D not triggering


I'm trying to trigger a print when CharacterBody2D collides with StaticBody2D. I'm very new to Godot please bear with me

I got 3 scenes game_level, CharacterBody2D (player), StaticBody2D (item). In game_level, I instantiated child Player and Item

I currently attached this script to the StaticBody2D (item):

extends StaticBody2D

func _ready():
    print("ready")
    

func _on_StaticBody2D_body_entered(body):
    print("Static body collided with: ", body.name)

I tried changing Collision Layer & Mask for both the CharacterBody2D and StaticBody2D as follows:

Just bumped but no prints

CharacterBody2D            || StaticBody2D
Collision>Layer = 1        || Collision>Layer = 1
Collision>Mask = 1         || Collision>Mask = 1

Just passed through but no prints

CharacterBody2D            || StaticBody2D
Collision>Layer = 1        || Collision>Layer = 2
Collision>Mask = 1         || Collision>Mask = 2

Just bumped but no prints

CharacterBody2D            || StaticBody2D
Collision>Layer = 1        || Collision>Layer = 2
Collision>Mask = 1 & 2     || Collision>Mask = 1 & 2

Godot Version: Godot_v4.0.1-stable_win64


Solution

  • In Godot Nodes have signals, which you can connect form the editor or from code. You need to connect the signal for them to work.

    I know you didn't connect the body_entered signal of your StaticBody2D.

    Making a method with the name that matches the that Godot would generate - in this case _on_StaticBody2D_body_entered - does not work.

    You can see if Godot recognized that a method has a signal connected because it shows a green icon on the left of the method declaration in the code editor.

    Please refer to Using Signals


    I know you didn't connect the body_entered signal of your StaticBody2D... Because StaticBody2D does not have a body_entered signal.

    It is possible to work around that. I have outlined some approaches elsewhere. And I won't repeat them here.

    With that said, my recommendation is to not use an StaticBody2D but an Area2D instead.

    If you need it to be an StaticBody2D, then I suggest adding a child Area2D to the StaticBody2D and use that to detect the collisions (which is one of the options I mention elsewhere).


    For completeness I'll also mention that you can detect what the CharacterBody2D ran into. Like this:

    for index in get_slide_collision_count():
        var collision := get_slide_collision(index)
        prints(collision.get_collider())
    

    Which should be sufficient for the case of a CharacterBody2D and a StaticBody2D that does not move※, because if the StaticBody2D does not move, it won't run into the CharacterBody2D (in other words the collision would be result of the motion of the CharacterBody2D).

    ※: The recommended way to do moving platforms in Godot 4 is with an AnimatableBody2D which are StaticBody2D.