前言
在 Godot 4.x(包括 C# 和 GDScript)中,CollisionObject2D 是一个抽象基类,用于表示所有能参与碰撞检测或区域交互的 2D 节点。
它本身不能直接实例化,但有两个主要子类:
CollisionObject2D 的直接子类(Godot 4)
| 子类 | 说明 | 是否产生物理碰撞 | 是否触发信号 | 典型用途 |
|---|---|---|---|---|
PhysicsBody2D |
可参与物理模拟的“实体” | ✅ 是 | ✅(如被 Area 检测到) | 玩家、敌人、箱子等 |
Area2D |
非实体的“感应区域” | ❌ 否(无碰撞体积) | ✅(可检测进入/离开) | 伤害区、触发器、音效范围 |
注意:
这两个是 唯二的直接子类。
PhysicsBody2D 的子类(间接子类)
虽然 PhysicsBody2D 本身是 CollisionObject2D 的子类,但它还有自己的派生类,
因此以下节点也是 CollisionObject2D 的间接子类。
来自 PhysicsBody2D 的具体实现:
CharacterBody2D用于精确控制的角色(如玩家)
使用
MoveAndSlide()处理碰撞RigidBody2D受物理引擎完全控制(重力、冲量、碰撞反弹等)
StaticBody2D静态环境物体(地面、墙壁),不移动,但可被其他物理体碰撞
类型与关系
继承关系图
1 | Node |
区别
| 能力 | Area2D |
CharacterBody2D |
RigidBody2D |
StaticBody2D |
|---|---|---|---|---|
| 有碰撞体积 | ✅ | ✅ | ✅ | ✅ |
| 阻挡其他物体 | ❌ | ✅ | ✅ | ✅ |
| 受物理力影响 | ❌ | ❌ | ✅ | ❌ |
| 可编程移动 | ✅(位置) | ✅(速度+滑动) | ⚠️(不推荐直接设位置) | ❌(可设但不推荐) |
触发 BodyEntered |
✅(作为监听方) | ✅(可被 Area 监听) | ✅ | ✅ |
| 自身可监听碰撞 | ❌ | ✅(通过 MoveAndSlide) | ✅(通过信号) | ❌ |
注意
💡
Area2D虽然有碰撞形状(如CollisionShape2D),但不会阻挡任何物理体,仅用于“检测重叠”。
判断类型示例
1 | public override void _Ready() |
总结
- 只有两个直接子类:
PhysicsBody2D和Area2D - 所有能“被碰撞”或“检测碰撞”的 2D 节点都继承自
CollisionObject2D - 选择依据:
- 要阻挡+移动控制 →
CharacterBody2D - 要真实物理 →
RigidBody2D - 要静态环境 →
StaticBody2D - 要触发区域(不阻挡) →
Area2D
- 要阻挡+移动控制 →
Layer 与 Mask
在 Godot 的 2D 物理系统中,每个 CollisionObject2D 都有两个关键属性:
Collision Layer(碰撞层)
表示“我属于哪些层”。
其他对象如果其 mask 包含这些层,就能和我碰撞。
Collision Mask(碰撞掩码)
表示“我会检测哪些层上的对象”。
只有当对方在这些层中,我才尝试与其碰撞。
Area2D信号
1 | public override void _Ready() |
施加力
ApplyCentralImpulse 是 RigidBody2D(2D)或 RigidBody3D(3D)类中的一个方法,用于给刚体施加一个瞬时的中心冲量(impulse),从而立即改变其线性速度,而不影响角速度(即不会产生旋转)。
1 | public void ApplyCentralImpulse(Vector2 impulse) |
- 参数:
impulse—— 一个表示冲量大小和方向的向量(单位:kg·m/s)。 - 作用点:刚体的质心(中心)。
- 效果:只改变线性速度,不产生扭矩(因此不会引起旋转)。
仅对 RigidBody 有效CharacterBody2D、StaticBody2D 等不能使用此方法。只有 RigidBody2D/RigidBody3D 支持。
必须在物理过程中调用
建议在 _PhysicsProcess() 或信号回调(如碰撞检测)中调用,以确保与物理引擎同步。
冲量(Impulse) vs 力(Force)
| 类型 | 方法 | 特点 |
|---|---|---|
| 力(Force) | AddForce() / ApplyForce() |
持续作用,受物理帧和质量影响,适合持续推动(如汽车引擎)。 |
| 冲量(Impulse) | ApplyCentralImpulse() / ApplyImpulse() |
瞬时作用,立即改变速度,适合跳跃、爆炸、击退等瞬间动作。 |
示例
1 | // 水平移动:使用 Input.GetAxis 获取平滑输入 |
常用方法
其中
1 | SetCollisionMaskValue(3, false); |
是物体移动时关闭对层3的检测,可以穿透。
注意
上面关闭检测为什么还能检测到碰撞到物体是因为:这里还是获取设置状态这一帧的碰撞,后续帧是不能检测的。
方法
1 | public int GetSlideCollisionCount() |
- 返回值:
int,表示上一次MoveAndSlide()调用过程中发生的滑动碰撞数量。 - 适用节点:
CharacterBody2D
1 | GetSlideCollision(i) |
- 获取第
i次滑动碰撞的详细信息
其他方法
| 属性/方法 | 说明 |
|---|---|
.GetPosition() |
碰撞发生的世界坐标位置(Vector2) |
.GetNormal() |
碰撞面的法线方向(指向角色外部,Vector2) |
.GetTravel() |
本次移动中实际走过的位移(Vector2) |
.GetRemainder() |
未完成的剩余位移(因碰撞被阻挡的部分,Vector2) |
.GetCollider() |
碰撞到的对象(如 Node、RigidBody2D、StaticBody2D 等) |
.GetColliderVelocity() |
被碰撞对象的速度(如果它是移动的刚体) |
.GetColliderId() |
碰撞体的唯一 ID(可用于识别) |