RigidBody2D
2026/4/14大约 6 分钟
最后同步日期:2026-04-15 | Godot 官方原文 — RigidBody2D
RigidBody2D
节点继承关系
继承链:Node → CanvasItem → Node2D → PhysicsBody2D → RigidBody2D
继承自 PhysicsBody2D
| 类型 | 名称 | 说明 |
|---|---|---|
| 方法 | MoveAndCollide() | 移动并检测碰撞 |
| 方法 | TestMove() | 测试移动是否会碰撞(不实际移动) |
继承自 Node2D
| 类型 | 名称 | 说明 |
|---|---|---|
| 属性 | Position | 本地位置(相对于父节点) |
| 属性 | GlobalPosition | 全局位置 |
| 属性 | Rotation | 旋转角度(弧度) |
| 属性 | Scale | 缩放比例 |
| 属性 | Skew | 倾斜角度(弧度) |
| 方法 | Rotate() | 旋转指定弧度 |
| 方法 | ToGlobal() | 本地坐标转全局坐标 |
| 方法 | ToLocal() | 全局坐标转本地坐标 |
继承自 CanvasItem
| 类型 | 名称 | 说明 |
|---|---|---|
| 属性 | Visible | 是否可见 |
| 属性 | Modulate | 整体颜色叠加(乘法) |
| 属性 | SelfModulate | 自身颜色叠加(不影响子节点) |
| 属性 | ZIndex | 绘制层级(Z 轴排序) |
| 信号 | visibility_changed | 可见性变化时触发 |
| 方法 | GetGlobalMousePosition() | 获取鼠标全局坐标 |
继承自 Node
| 类型 | 名称 | 说明 |
|---|---|---|
| 属性 | Name | 节点名称 |
| 属性 | ProcessMode | 处理模式(始终 / 暂停时 / 仅编辑器) |
| 属性 | ProcessPriority | 处理优先级,数字越小越先执行 |
| 信号 | ready | 节点进入场景树并准备就绪 |
| 信号 | tree_entered | 节点进入场景树 |
| 信号 | tree_exited | 节点完全离开场景树 |
| 方法 | GetNode<T>() | 按路径获取子节点 |
| 方法 | AddChild() | 添加子节点 |
| 方法 | RemoveChild() | 移除子节点 |
| 方法 | QueueFree() | 帧结束后释放节点 |
| 方法 | GetParent() | 获取父节点 |
定义
受 2D 物理引擎完全控制的物体——你给它一个力,引擎就帮你算出它该怎么飞、怎么转、怎么弹。
想象你在打台球——你用球杆推一下白球(给它一个力),然后白球就按照物理规律去滚、去碰别的球、去弹回来。RigidBody2D 就是那个"球"。你不用写移动代码,只需要告诉物理引擎"给它多少力",引擎就会帮你模拟真实的运动。
关键区别:CharacterBody2D 是你自己控制速度,RigidBody2D 是物理引擎控制速度。所以——千万不要直接修改 RigidBody2D 的 position(位置),要移动它,请用"施加力"的方式。
使用频率:★★★ 一般常用——常用于需要真实物理效果的物体。
节点用途
- 可推动的箱子、桶
- 台球、弹球
- 投掷物(手雷、飞刀)
- 碎片、掉落物
- 任何需要真实物理效果(弹跳、旋转)的物体
使用场景
典型场景
- 可推动的箱子:玩家碰到箱子时箱子被推走
- 弹球物理:球碰到墙壁弹回来
- 投掷武器:手雷抛出后受重力影响飞行
不适用场景
- 需要自己精确控制移动的角色 → 使用 CharacterBody2D
- 永远不动的墙壁 → 使用 StaticBody2D
- 只需检测进出的区域 → 使用 Area2D
常用节点搭配
| 搭配节点 | 用途 | 必需? |
|---|---|---|
| CollisionShape2D | 定义物体的碰撞边界 | 必需 |
| Sprite2D | 显示物体的外观 | 推荐 |
典型节点树:
PushableBox (RigidBody2D)
├── CollisionShape2D
└── Sprite2D生效必备素材/资源
| 资源 | 类型 | 说明 |
|---|---|---|
| 碰撞形状(如 RectangleShape2D) | Shape2D 资源 | 赋给 CollisionShape2D 子节点 |
节点属性与信号
物理参数
| 属性 | 类型 | 默认值 | 继承自 | 说明 |
|---|---|---|---|---|
Mass | float | 1.0 | — | 质量,影响受力后的加速度(力 / 质量 = 加速度) |
GravityScale | float | 1.0 | — | 重力倍数:0 = 不受重力,2 = 双倍重力,-1 = 反重力 |
LinearVelocity | Vector2 | (0, 0) | — | 线速度(直线移动的速度) |
AngularVelocity | float | 0.0 | — | 角速度(旋转速度,弧度/秒) |
LinearDamp | float | 0.0 | — | 线性阻尼(空气摩擦,越大减速越快) |
AngularDamp | float | 0.0 | — | 角度阻尼(旋转摩擦) |
Bounce | float | 0.0 | — | 弹性系数:0 = 不弹,1 = 完美弹跳 |
Friction | float | 1.0 | — | 摩擦系数:0 = 像冰面一样滑 |
碰撞检测
| 属性 | 类型 | 默认值 | 继承自 | 说明 |
|---|---|---|---|---|
ContactMonitor | bool | false | — | 是否监测碰撞(开启后才能接收碰撞信号) |
MaxContactsReported | int | 0 | — | 最大报告碰撞数(和 ContactMonitor 搭配使用) |
CanSleep | bool | true | — | 物体静止时是否"休眠"以节省性能 |
物理材质(Physics Material)覆盖
| 属性 | 类型 | 默认值 | 继承自 | 说明 |
|---|---|---|---|---|
PhysicsMaterialOverride | PhysicsMaterial | null | — | 自定义物理材质(统一设置弹性和摩擦) |
信号
| 信号 | 触发时机 | 继承自 | 说明 |
|---|---|---|---|
body_entered(body) | 有物理体碰到它 | PhysicsBody2D | 需开启 ContactMonitor |
body_exited(body) | 有物理体离开它 | PhysicsBody2D | 需开启 ContactMonitor |
body_shape_entered(body_rid, body, body_shape_index, local_shape_index) | 碰撞形状进入 | PhysicsBody2D | 需开启 ContactMonitor |
sleeping_state_changed() | 物体进入/退出休眠 | RigidBody2D | — |
常用方法
| 方法 | 返回值 | 说明 |
|---|---|---|
ApplyForce(force) | void | 施加持续力(像推车,推多久走多远) |
ApplyImpulse(impulse) | void | 施加瞬间冲量(像踢一脚,只作用一次) |
ApplyTorque(torque) | void | 施加旋转力矩(让它转起来) |
ApplyTorqueImpulse(impulse) | void | 施加瞬间旋转冲量 |
ApplyCentralForce(force) | void | 施加中心力(不会引起旋转) |
ApplyCentralImpulse(impulse) | void | 施加中心瞬间冲量 |
ApplyForceAtPosition(force, position) | void | 在指定位置施加力(会引起旋转) |
ApplyImpulseAtPosition(impulse, position) | void | 在指定位置施加冲量 |
SetAxisVelocity(axisVelocity) | void | 设置某个轴方向的速度 |
GetCollidingBodies() | GodotArray[Node] | 获取所有碰撞的物体列表 |
代码示例
C
using Godot;
/// <summary>
/// 可推动的箱子:玩家碰到时会推动它
/// 节点结构:PushableBox (RigidBody2D) + Sprite2D + CollisionShape2D
/// </summary>
public partial class PushableBox : RigidBody2D
{
[Export] public float ExPushForce = 500.0f; // 推力大小
// 当有物体碰到这个箱子时触发
public void OnBodyEntered(Node body)
{
if (body is CharacterBody2D player)
{
// 计算推力方向:从玩家指向箱子的方向
Vector2 direction = (GlobalPosition - player.GlobalPosition).Normalized();
// 施加中心冲量(踢一脚)
ApplyCentralImpulse(direction * ExPushForce);
}
}
}
/// <summary>
/// 手雷:抛出后受重力影响,碰到地面后爆炸
/// 节点结构:Grenade (RigidBody2D) + Sprite2D + CollisionShape2D + Timer
/// </summary>
public partial class Grenade : RigidBody2D
{
[Export] public float ExThrowForce = 600.0f; // 投掷力度
[Export] public float ExFuseTime = 2.0f; // 引信时间(秒)
[Export] private PackedScene _explosionScene; // 爆炸特效场景
private Timer _fuseTimer;
public override void _Ready()
{
_fuseTimer = GetNode<Timer>("Timer");
_fuseTimer.WaitTime = ExFuseTime;
_fuseTimer.OneShot = true;
_fuseTimer.Timeout += Explode;
_fuseTimer.Start();
}
/// <summary>
/// 初始化投掷方向和力度
/// </summary>
public void Throw(Vector2 direction)
{
ApplyCentralImpulse(direction * ExThrowForce);
}
private void Explode()
{
// 生成爆炸特效
if (_explosionScene != null)
{
var explosion = _explosionScene.Instantiate<Node2D>();
GetTree().CurrentScene.AddChild(explosion);
explosion.GlobalPosition = GlobalPosition;
}
// 销毁手雷
QueueFree();
}
}GDScript
# 可推动的箱子:玩家碰到时会推动它
# 节点结构:PushableBox (RigidBody2D) + Sprite2D + CollisionShape2D
extends RigidBody2D
@export var push_force: float = 500.0 # 推力大小
# 当有物体碰到这个箱子时触发
func _on_body_entered(body: Node) -> void:
if body is CharacterBody2D:
# 计算推力方向:从玩家指向箱子的方向
var direction := (global_position - body.global_position).normalized()
# 施加中心冲量(踢一脚)
apply_central_impulse(direction * push_force)不要直接改 RigidBody 的位置!
Position、GlobalPosition 这些属性由物理引擎控制。如果你在代码里直接修改它们,物体可能会出现"瞬移"、"穿墙"、"抖动"等奇怪行为。
想移动 RigidBody?用这几种方式:
- 施加力:
ApplyForce()—— 像持续推它 - 施加冲量:
ApplyImpulse()—— 像踢它一脚 - 设置速度:直接改
LinearVelocity(可以,但不太推荐)
如果必须直接改位置(比如传送),请使用 GlobalPosition 在物理帧内处理,或者使用 ForceUpdateTransform()。
