HOME / 第 3 部分 · 2D 游戏开发实战 / 第 21 课
MODULE 3 · 2D 游戏开发实战

第 21 课 · CharacterBody2D:重力与跳跃

⏱ 预计时长 40 分钟📊 难度 入门📚 模块 第 3 部分 · 2D 游戏开发实战

🎯 本课学习目标

CharacterBody2D 是做「角色」的专用物理体。本课实现完整的平台跳跃角色:重力、跳跃、左右移动。

📖 详细教学步骤

准备玩家场景搭建

新建场景,根节点为 CharacterBody2D,命名 Player,保存 player.tscn;子节点:Sprite2D(角色图)+ CollisionShape2D(胶囊形);给根节点挂脚本 player.gd。

💡 CharacterBody2D 的核心是手动维护 velocity 再调用 move_and_slide()

物理移动核心:velocity + move_and_slide概念

CharacterBody2D 的移动规范:把速度存在内置 velocity 里,每帧调用 move_and_slide() 执行移动+碰撞。

GDSCRIPTextends CharacterBody2D

@export var speed: float = 200.0
@export var gravity: float = 980.0        # 重力加速度
@export var jump_velocity: float = -400.0  # 起跳速度(负=向上)

func _physics_process(delta):
    # 1) 始终加重力(在地面时不加)
    if not is_on_floor():
        velocity.y += gravity * delta

    # 2) 水平移动
    var dir = Input.get_axis("move_left", "move_right")
    velocity.x = dir * speed

    # 3) 跳跃:按跳跃键且在地面上
    if Input.is_action_just_pressed("jump") and is_on_floor():
        velocity.y = jump_velocity

    # 4) 执行移动(处理碰撞)
    move_and_slide()

创建跳跃输入映射操作

项目设置 → 输入映射中创建动作:

  • jump:绑定空格键 Space
  • move_left:绑定 A / ←
  • move_right:绑定 D / →

💡 Input.get_axis("move_left","move_right") 返回 -1~1:按左=-1、按右=1、都不按=0,斜向也不会有问题。

了解 is_on_floor 等状态检测概念

  • is_on_floor():是否站在地面上
  • is_on_wall():是否贴着墙
  • is_on_ceiling():是否顶着天花板

这些由 move_and_slide() 每帧自动更新。

搭测试平台并运行集成

  1. main.tscn 里放 StaticBody2D 地面(矩形碰撞 + 可视化颜色块),把玩家实例放上去
  2. F5 运行:左右移动、空格跳跃、落地
  3. 若跳不起来:检查 jump 动作是否创建、是否 is_on_floor

🎉 经典平台跳跃手感达成!

⚠️
玩家一运行就往下掉不停?

正常,有重力就该掉。需要地面 StaticBody2D + CollisionShape2D 挡住。若穿透,检查地面碰撞形状是否在玩家下方且足够宽。

⚠️
跳跃太高/太低?

调 jump_velocity(越负跳越高)和 gravity(越大落得越快)。推荐先试 jump_velocity=-400、gravity=980。

⚠️
斜着卡墙角?

把 CollisionShape2D 适当调小,或调整 floor_max_angle。

🧪 动手试一试

🏋️ 课后练习

实现「二段跳」:在空中再按一次跳跃能再跳一次(最多二段)。

var jump_count=0; 落地时 jump_count=0; 起跳条件为按下跳跃且 (is_on_floor() or jump_count<2),起跳时 jump_count+=1。

💡

velocity 是内置属性,直接赋值即可。

💡

重力 980 是默认值,轻快手感调小、沉重手感调大。

🎓 本课小结

CharacterBody2D 规范:维护 velocity → 加重力 → 设水平速度 → 判断跳跃 → move_and_slide();用 is_on_floor() 判断落地。