如何检测 Godot 中的 KinematicBody2D 和 RigidBody2D 之间的碰撞?

How do I detect collisions between a KinematicBody2D and a RigidBody2D in Godot?

我正在尝试在 Godot 中制作一个简单的游戏,其中一堵墙倒塌,玩家必须躲避它。墙是一个附有 sprite 和 CollisionShape2D 的 RigidBody2D。播放器是一个带有精灵和 CollisionShape2D 的 KinematicBody2D。主场景是一个 Node2D,播放器和墙是它的 children。我已经设法让播放器检测到碰撞,但是当我发出信号(连接到墙脚本)时,墙什么都不做。我已经尝试在播放器脚本中使用 body_entered 信号,但没有任何反应。有人知道如何解决这个问题吗?

我的播放器脚本:

extends KinematicBody2D

var speed = 1300
var velocity = Vector2()
signal game_over

func get_input():
velocity = Vector2()
if Input.is_action_pressed('d'):
    velocity.x += 1
if Input.is_action_pressed('a'):
    velocity.x -= 1
velocity = velocity.normalized() * speed

func _physics_process(delta):
get_input()

move_and_slide(velocity, Vector2(0, 0), false, 4, 0.785, false)

for index in get_slide_count():
    var collision = get_slide_collision(index)
    if collision.collider.is_in_group("Level"):
        death()

func death():
    emit_signal("game_over")
    hide()

壁画:

extends RigidBody2D

func _on_Player_game_over():
    print("player collided") #example to see if collision is detected

我不知道为什么你的代码不起作用。但是,我会做不同的事情:不是发出信号,而是在 collider:

上调用一个方法
    if collision.collider.is_in_group("Level"):
        collision.collider._on_Player_game_over()
        death()

可能值得为该方法起一个更好的名称。

对了,你也可以看看collider有没有这个方法。例如:

    if collision.collider.has_method("_on_Player_game_over"):
        collision.collider._on_Player_game_over()
        death()

这个答案的其余部分解释了如何处理 RigidBody2D"body_entered" 信号的冲突。

  • 首先确保 RigidBody2D 已将 contact_monitor 设置为 true

  • 同时将其 contacts_reported 设置为大于 0 的值。同一个 body 可以有多个联系人,您需要考虑与其他机构的可能联系人。 8 左右的值可能没问题。

  • RigidBody2D"body_entered" 信号 连接到自身

  • RigidBody2D 中处理 "body_entered" 信号的方法中你会得到一个 body 参数:

    func _on_Wall_body_enter(body):
        print("Collision")
    

    顺便提一下,我鼓励大家利用碰撞层和遮罩。因此,您可以缩小 RigidBody2D 甚至检查的碰撞范围。

  • 然后你可以过滤body是什么。例如,您可以:

    • 使用姓名:

      func _on_Wall_body_enter(body):
          if body.name == "Player":
              print("Collision with player")
      
    • 使用群组:

      func _on_Wall_body_enter(body):
          if body.is_in_group("Player"):
              print("Collision with player")
      
    • 使用class名称(这需要给播放器添加class_name):

      func _on_Wall_body_enter(body):
          if body is Player:
              print("Collision with player")
      
    • 检查方法:

      func _on_Wall_body_enter(body):
          if body.has_method("death"):
              print("Collision with player")
      
  • 当然,你可以在它上面调用一个方法notify。例如:

    func _on_Wall_body_enter(body):
        if body is Player:
            body.death()
    

    func _on_Wall_body_enter(body):
        if body.has_method("death"):
            body.death()