Godot进行2D游戏开发入门-实现人物的移动和跳跃(输入映射)

前言

我们先从一个简单的人物移动跳跃的示例来学习使用节点和设置输入映射及绑定脚本。

日志打印

1
GD.Print("Hello World");

添加如下节点

image-20260105233628451

CharacterBody2DStaticBody2D 是两种不同类型的 2D 物理节点,它们在用途、行为和性能上有显著区别。

以下是它们的核心差异:

用途与角色

  • CharacterBody2D(Godot 4 中取代了旧版的 KinematicBody2D

    • 用于可移动的角色,如玩家、敌人、NPC 等。
    • 设计用于主动移动并检测碰撞,但不参与物理模拟(不受重力、力等影响,除非你手动实现)。
    • 使用 MoveAndSlide()MoveAndCollide() 方法进行移动,并自动处理滑动、斜坡、碰撞响应。
  • StaticBody2D

  • 用于静止不动的环境物体,如墙壁、地面、平台、障碍物等。
    • 不会移动(即使施加力也不会动),主要用于与其他物理体(如 CharacterBody2DRigidBody2D)发生碰撞。
  • 参与物理世界,作为碰撞几何体存在,但自身无速度、无动力学行为。

物理行为

特性 CharacterBody2D StaticBody2D
可移动 ✅(通过代码控制) ❌(固定不动)
受物理引擎力影响(如重力) ❌(需手动实现)
会与其他物理体碰撞
会触发信号(如 BodyEntered ❌(默认不支持 Area 类信号) ❌(本身不是 Area)
性能开销 中等(每帧可能移动+碰撞检测) 极低(静态,优化良好)

⚠️ 注意:

如果你需要检测进入/离开事件,通常需要搭配 Area2D 使用。

添加输入映射

要响应按键事件,我们可以添加自定义输入映射

系统自带了一些内置动作,不建议使用,建议自己添加。

项目 => 项目设置 => 输入映射

我这里添加了如下的映射

image-20260105234449092

设置层

项目 => 项目设置 => 常规 => 层名称 => 2D 物理

设置层的名称,这里主要方便我们后续设置的时候,知道层的用途。

image-20260105234730487

选中CharacterBody2D节点

Collision 中

  • Layer是设置当前节点属于哪个层
  • Mask 是指能和哪些层发生碰撞

如图

image-20260105235030645

所以StaticBody2D,作为地面,Mask 可以不设置

image-20260105235316544

点击右侧的三个点,可以根据我们之前设置的层名称选择

image-20260105235449669

添加角色脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
using Godot;
using System;

public partial class Player : CharacterBody2D
{
// 导出变量,可在编辑器中调整
[Export]
public float MoveSpeed = 200.0f;

[Export]
public float JumpForce = -400.0f;

// 重力(从项目设置中读取默认值)
private float gravity;

private int jumpUsed = 0;
private int jumpMax = 2;

public override void _Ready()
{
// 初始化重力(单位:像素/秒²)
gravity = ProjectSettings.GetSetting("physics/2d/default_gravity").AsSingle();
}

public override void _PhysicsProcess(double delta)
{
Vector2 velocity = Velocity;

// 应用重力(仅当不在地面时)
if (!IsOnFloor())
{
velocity.Y += gravity * (float)delta;
}
else
{
// 可选:防止因浮点误差导致 Y 速度残留
velocity.Y = 0;
jumpUsed = 0;
}

// 水平移动:使用 Input.GetAxis 获取平滑输入
float horizontalInput = Input.GetAxis("move_left", "move_right");
velocity.X = horizontalInput * MoveSpeed;

// 跳跃
if (Input.IsActionJustPressed("jump") && jumpUsed < jumpMax)
{
velocity.Y = JumpForce;
jumpUsed += 1;
}

// 更新速度并移动
Velocity = velocity;
MoveAndSlide();
}
}

_Process 和 _PhysicsProcess

在 Godot 引擎中(使用 C# 开发时),_Process_PhysicsProcess 是两个核心的内置回调方法,用于在每一帧执行逻辑。

它们的关键区别在于调用频率、用途和与物理引擎的同步性

  • _Process(delta):每帧调用,适合非物理相关的逻辑(如 UI、动画、输入响应)。
  • _PhysicsProcess(delta)固定频率调用(默认 60Hz),专用于物理、移动、碰撞等需要稳定性的操作

_Process是渲染的回调,会不稳定,假如是稳定的是120Hz,如果我们在这里面检测节点的碰撞,就会重复,因为渲染的速度是物理运动计算帧率的2倍。

使用建议:

任务类型 推荐方法
玩家/敌人移动、跳跃、重力 _PhysicsProcess
摄像机跟随(平滑) _Process(视觉跟随)或 _PhysicsProcess(锁定物理)
按键输入读取 两者都可,但移动相关输入应在 _PhysicsProcess 中处理
UI 更新、血条、计分 _Process
动画播放(AnimationPlayer) _Process(默认已同步)
粒子、特效 _Process

最佳实践

  • 所有涉及 MoveAndSlide()VelocityRigidBody2D 力的操作 → _PhysicsProcess
  • 其他一切 → _Process