Godot 2D 物理

4.5.1 2025-10-15

可以简单为认为三种物理类型,静态物体(StaticBody2D),刚体(RigidBody2D),角色(CharacterBody2D)。

静态物体(StaticBody2D)很好理解,地板,墙壁之类,静止不动的物体,可以碰撞,但是推不动。

刚体(RigidBody2D),刚体原本和柔性物体对应,但是2D没有柔性物体,所以就简单认为刚体是可以互相碰撞、推动、反弹的通常意义上的物理系统里的物体吧。可以给刚体加一个速度,然后让它们自己去移动碰撞。

角色(CharacterBody2D),角色比较特殊,它是一个我们主动控制,并且能和其他物体碰撞的物体,可以让我们更精准的控制角色的移动碰撞和反应。

在这三种基本物体之上,还可以使用只检测碰撞范围,不会发生碰撞反弹的区域(Area2D),还有主动检查碰撞的射线(Ray),还可以把多个刚体使用铰链(Joint)连接起来。

角色(CharacterBody2D)

角色封装了常用操作,帮助开发者控制角色的移动和碰撞。


# 左右移动速度
const SPEED = 300.0
# 跳跃速度
const JUMP_VELOCITY = -400.0

func _physics_process(delta: float):
  # 如果没落到地板上
  if not is_on_floor():
    # 重力下落
    velocity += get_gravity() * delta

  # 按空格跳跃
  if Input.is_action_just_pressed("ui_accept") and is_on_floor():
    velocity.y = JUMP_VELOCITY

  # 向左还是向右移动
  var direction := Input.get_axis("ui_left", "ui_right")
  if direction:
    # 向按键方向移动
    velocity.x = direction * SPEED
  else:
    # 如果未按键,减速
    velocity.x = move_toward(velocity.x, 0, SPEED)

  # 移动,碰撞,滑动
  move_and_slide()
          

如果想实现更复杂的碰撞反应,比如碰撞后不向侧向滑动,可以使用 move_and_collide() 手工处理碰撞后的行为。


# 移动并碰撞
var collision = move_and_collide(velocity * delta)
if collision:
  # 若碰撞,可以通过collision获取碰撞到的对象
  print("I collided with ", collision.get_collider().name)
  # 可以基于碰撞法线方向(get_normal)实现速度反弹
  velocity = velocity.bounce(collision.get_normal())