关于 physics-system
面向 Godot 4.3+ 开发者的物理系统技能,讲解碰撞体、刚体、区域、查询与插值等实践,并涵盖 Jolt Physics 和布娃娃系统。
主要功能
- 01区分四类物理碰撞对象
- 02配置碰撞形状、层与遮罩
- 03通过射线和空间状态查询
- 04使用 Jolt Physics 进行 3D 物理
- 05设置物理插值与布娃娃
适用场景
- 01制作玩家、敌人与可交互物体的碰撞
- 02实现触发区域、重力区或音频区
- 03进行射线检测和 3D 鼠标拾取
- 04为角色制作布娃娃物理效果
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ jame581/ godotprompter --skill physics-system安装后在 Claude Code 中输入/physics-system确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/area-recipes.mdcollision-layers.mdcollision-shapes.mdinterpolation-camera.mdinterpolation-tuning.mdjolt-differences.mdragdoll-recipes.mdraycasting-recipes.mdrigidbody-recipes.mdsoftbody-recipes.mdstaticbody-recipes.mdtroubleshooting.md详细介绍
Godot 4.3+ 中的物理系统
所有示例均面向 Godot 4.3+,不使用已弃用的 API。先展示 GDScript,再展示 C#。
相关技能: player-controller 用于 CharacterBody2D/3D 移动模式,component-system 用于 hitbox/hurtbox 组合,godot-optimization 用于物理性能调优,camera-system 用于摄像机跟随和插值,multiplayer-sync 用于网络物理同步,2d-essentials 用于图块碰撞设置和 2D 画布层。
1. 物理体类型
四种碰撞对象类型(后三种继承自 PhysicsBody2D/3D):
| 类型 | 移动方式 | 用途 |
|---|---|---|
Area2D/3D | 代码 | 重叠检测、重力区域、音频区域 |
StaticBody2D/3D | 不移动(或使用 constant_linear_velocity) | 墙壁、地板、传送带 |
RigidBody2D/3D | 物理引擎 | 板条箱、投射物、碎片、布娃娃 |
CharacterBody2D/3D | 代码 | 玩家、敌人、NPC(参见 player-controller) |
每个碰撞对象都至少需要一个 CollisionShape2D/3D(或 CollisionPolygon2D/3D)子节点。自 4.4 起内置 Jolt Physics(实验性,需选择启用),并且是 4.6+ 中新建项目的默认 3D 引擎——参见第 8 节;现有项目会继续使用 GodotPhysics,直到切换为止。2D 始终使用 GodotPhysics。
**关键规则:**绝不要通过
scale缩放碰撞形状或物理体。应使用形状自身的尺寸参数(半径、半尺寸、高度)——缩放会降低碰撞精度。
2. RigidBody2D/3D
力与冲量
| 方法 | 效果 | 使用场景 |
|---|---|---|
apply_force(force, position) | 在作用点持续加速 | 推进器、风、磁铁 |
apply_central_force(force) | 在中心持续加速 | 重力、持续推力 |
apply_impulse(impulse, position) | 在作用点瞬间改变速度 | 子弹命中、爆炸 |
apply_central_impulse(impulse) | 在中心瞬间改变速度 | 跳跃、击退 |
apply_torque(torque) | 持续角加速 | 转向、旋转 |
apply_torque_impulse(impulse) | 瞬间改变角速度 | 撞击旋转 |
关于使用
apply_force+apply_central_impulse+apply_torque的推力与旋转示例(GDScript + C#),请参见 references/rigidbody-recipes.md。
_integrate_forces() — 安全修改物理状态
使用 _integrate_forces(state) 而不是 _physics_process() 来读取或修改 RigidBody 的变换、速度或角速度。在 _physics_process() 中直接设置 position 或 linear_velocity 会与物理引擎争夺控制权。
**警告:**物体休眠时不会调用
_integrate_forces()。如果需要持续回调,请设置can_sleep = false;否则,让物体休眠以提升性能。
关于使用
state.apply_force/state.apply_torque的推力与扭矩示例(GDScript + C#),请参见 references/rigidbody-recipes.md。
接触监控、PhysicsMaterial、冻结、look_at
- 接触信号需要设置
contact_monitor = true和max_contacts_reported > 0。之后会触发body_entered/body_exited。 PhysicsMaterial资源用于控制friction(0 为冰面 → 1 为橡胶)和bounce(0 → 1)。- 冻结模式:
FREEZE_MODE_STATIC(表现为 StaticBody)或FREEZE_MODE_KINEMATIC(由代码移动,并推动其他物体)。 - **RigidBody3D 朝向:**不要对 RigidBody 调用
look_at()——应使用_integrate_forces,并根据叉积转向项设置state.angular_velocity。
关于完整的 GDScript + C# 示例(包含
take_damage的接触处理器、PhysicsMaterial 属性表、冻结切换,以及通过角速度实现 RigidBody3D 追踪目标),请参见 references/rigidbody-recipes.md。
3. StaticBody2D/3D
StaticBody 不会由物理引擎移动,但可以通过 constant_linear_velocity 推动其他物体(例如传送带)。对于通过代码移动并推动 CharacterBody 的平台,请使用 AnimatableBody2D/3D——通过代码移动的 StaticBody 无法可靠地推动 CharacterBody。
请参阅 references/staticbody-recipes.md,了解传送带和移动平台的配方(GDScript + C#,以及由 Tween 驱动的 AnimatableBody2D 循环)。
4. Area2D/3D
Area 会检测重叠,并覆盖其范围内的物理属性。它们不会产生碰撞响应——物体会直接穿过。只有在 monitoring 开启,且其 collision_mask 包含物体的 collision_layer 时,Area 才会报告该物体——两者不匹配是 body_entered 从不触发的常见原因,因此即使默认值(layer 1、mask 1)恰好匹配,也要明确说明这两个设置。对于物体重叠,请连接 body_entered / body_exited;对于 Area 之间的重叠(hitbox 与 hurtbox——参见 component-system),请使用 area_entered / area_exited。Area 还可以覆盖重力(零重力区域、点重力/黑洞)、linear_damp / angular_damp(水、慢动作),并将音频重定向到特定的 AudioBus。多个 Area 重叠时,由 priority 决定顺序;请选择一种 space_override 模式(COMBINE、REPLACE、COMBINE_REPLACE、REPLACE_COMBINE)。
请参阅 references/area-recipes.md,了解 GDScript + C# 重叠检测的标准示例、space-override 模式参考表,以及零重力和点重力配方。
⚠️ Godot 4.7 中的变更: 使用 Jolt Physics 时,
Area3D现在会通过其信号和方法报告与SoftBody3D的重叠。请配置碰撞层/遮罩,忽略不需要的Area3D↔SoftBody3D交互。请参阅 4.7 migration guide。
5. Collision Shapes
| 形状(2D / 3D) | 用途 |
|---|---|
Rectangle / Box | 箱子、平台、房间 |
Circle / Sphere | 球、投射物、简单角色、触发区域 |
Capsule(2D 和 3D) | 角色——圆角,可沿边缘滑动 |
Segment2D / — | 薄墙、激光束 |
SeparationRay2D / 3D | 角色贴地 |
WorldBoundary2D / 3D | 无限延伸的地面/墙壁/天花板 |
— / Cylinder3D | 柱子、木桶(GodotPhysics 存在已知问题——建议使用 Jolt) |
动态物体优先使用基本形状。ConvexPolygonShape 速度快,但无法表示孔洞或向内弯曲的形状;ConcavePolygonShape 对关卡几何体的表示精确,但仅适用于 StaticBody,且速度最慢。切勿平移、旋转或缩放 CollisionShape 节点——形状不经过变换才能启用宽相位优化。Godot 4.7+ 新增了用于横向单向平台的 one_way_collision_direction。
凸/凹形状成本表、形状生成菜单、完整的性能规则,以及 4.7+ 单向方向 API(GDScript + C#):references/collision-shapes.md
6. Collision Layers and Masks
Godot 为每个维度提供 32 个物理层(2D 和 3D 各自独立)。
- collision_layer ——此物体所在的层(其他物体会在此处扫描它)
- collision_mask ——此物体扫描的层(它会检测哪些物体)
理解方式: Layer =“我所在的层”,Mask =“我扫描的层”。当物体 A 的 mask 包含物体 B 的 layer,或反之时,就会发生碰撞。
在 Project Settings → Layer Names → 2D Physics(或 3D Physics)中为层命名;在代码中使用 set_collision_layer_value(N, true) / set_collision_mask_value(N, true) 设置(索引从 1 开始)。
请参阅 references/collision-layers.md,了解层命名约定、位掩码简写、Inspector 导出标志,以及 GDScript + C# 示例。
7. Raycasting and Physics Queries
RayCast2D/3D 节点(简单的逐帧射线)
将 RayCast2D / RayCast3D 添加为子节点——它会在每个物理帧自动进行射线检测。使用 is_colliding() 和 get_collider() / get_collision_point() / get_collision_normal() 读取结果。
请参阅 references/raycasting-recipes.md,了解 GDScript + C# 的 RayCast 节点示例。
基于代码的射线检测(PhysicsDirectSpaceState)
对于按需查询,可通过 get_world_2d().direct_space_state(或 get_world_3d())访问空间状态,并使用 PhysicsRayQueryParameters2D/3D.create(from, to) 调用 intersect_ray(query)。设置 query.exclude = [get_rid()] 可跳过自身,设置 query.collision_mask 可筛选图层。请在 _physics_process() 中查询——物理步骤运行期间空间处于锁定状态;如果物理运行在单独的线程上,则只能在此处访问。
请参阅 references/raycasting-recipes.md,了解完整的基于代码的射线检测示例(GDScript + C#),其中包括排除自身和筛选遮罩,以及 3D 鼠标拾取教程。
射线结果、其他查询和 3D 鼠标拾取
intersect_ray 的结果字典包含 position、normal、collider、collider_id、rid、shape。PhysicsDirectSpaceState 还支持 intersect_point(查询点处重叠的形状)、intersect_shape(区域查询)、cast_motion(形状扫掠)、collide_shape(接触点)、get_rest_info(静止碰撞信息)。对于 3D 鼠标拾取,Camera3D.project_ray_origin(screen_pos) + project_ray_normal(screen_pos) 可构建射线。
请参阅 references/raycasting-recipes.md,了解完整的鼠标拾取教程(GDScript + C#)。
8. Jolt Physics
Jolt 是内置的替代物理引擎,自 Godot 4.4 起可作为实验性选项启用。(Godot 4.6+) Jolt 不再标记为实验性,并且是新建 3D 项目的默认选项;从早期版本升级的项目会继续使用 DEFAULT(GodotPhysics3D),直到手动更改。
启用 Jolt
项目设置 → 物理 → 3D → 物理引擎 → Jolt Physics → 保存 → 重启编辑器。(仅限 3D;2D 始终使用 GodotPhysics。)
优势与差异
优势: 堆叠稳定性更好;CylinderShape3D 不存在 GodotPhysics 中已知的圆柱体错误;SoftBody3D 表现更好;支持活动边缘检测(可减少幽灵碰撞)。
请参阅 references/jolt-differences.md,了解与 GodotPhysics 的行为差异(稳定性、碰撞边距、单体关节、
face_index、不受支持的关节属性)。
⚠️ Godot 4.7 中的变更: 使用 Jolt Physics 时,
WorldBoundaryShape3D.plane.d现在与 Godot Physics 遵循相同的符号约定——与 Godot 4.6 相比,平面距离的解释符号相反。若要保持 4.6 中的行为,请自行翻转符号。请参阅 4.7 迁移指南。
9. 物理插值
在物理帧之间平滑视觉运动,消除物理帧率 ≠ 渲染帧率时的“阶梯状”抖动。可在 项目设置 → 物理 → 常规 → 物理插值 中启用(4.3 仅插值 2D;从 4.4 起支持 3D)。Godot 4.5+ 重构了 3D 插值管线(RenderingServer → SceneTree),使嵌套变换的结果更加准确——API 没有变化,升级后即可自动获得改进。
核心规则
- 将所有游戏逻辑移至
_physics_process()——在物理帧之外设置变换会导致抖动 - 移动物理对象的 Tween 和 AnimationPlayer 必须使用物理帧计时
- 传送或进行初始放置后调用
reset_physics_interpolation(),以防止出现“拖影”
请参阅 references/interpolation-tuning.md,了解传送后重置示例(GDScript + C#)、逐节点的
physics_interpolation_mode控制方法,以及物理帧率指南。
摄像机插值
在物理插值下,摄像机需要特殊处理。将摄像机设为独立节点(或设置 top_level = true),在 _process()(而非 _physics_process())中更新,并通过 Node3D.get_global_transform_interpolated()(4.4+)读取目标的平滑位置。
完整的平滑跟随 Camera3D 实现方案(GDScript + C#)请参阅 references/interpolation-camera.md。
10. 布娃娃系统
布娃娃会用物理模拟替代动画,可用于程序化死亡、爆炸或软趴趴的角色。通过 Skeleton3D → Skeleton 菜单 → Create Physical Skeleton 生成。肩部、髋部和颈部使用 ConeJoint,肘部和膝部使用 HingeJoint——PinJoint(默认)往往会导致骨架皱缩。通过 physical_bones_start_simulation() 驱动,并使用 Influence 混合。
有关设置、关节选择建议、完整的 GDScript + C# 控制、动画混合和碰撞例外,请参阅 references/ragdoll-recipes.md。
11. SoftBody3D
SoftBody3D 可模拟可变形物体(布料、披风、果冻)。网格细分决定模拟效果;无需添加 CollisionShape 子节点。推荐使用 Jolt Physics。 将 Simulation Precision 设为 ≥ 5,以防止物体塌陷。Pressure > 0.0 仅适用于封闭网格。
Godot 4.5+ 为 RigidBody3D 风格的施力操作新增了 apply_central_impulse() / apply_central_force()——施力会分布到所有模拟点。
布料/披风操作指南(PlaneMesh、BoneAttachment3D 固定、Parent Collision Ignore),以及使用 GDScript 和 C# 的 4.5+ 力/冲量 API(爆炸击退、持续风力),请参阅 references/softbody-recipes.md。
⚠️ Godot 4.7 中的变更: 使用 Jolt Physics 时,
SoftBody3D的质量不再默认为0(这会自动按每个点 1 kg 计算,导致总质量非常高),而是默认整个物体为 1 kg,与 Godot Physics 一致。linear_stiffness的应用方式也有所不同,因此升级后请重新调整linear_stiffness和damping_coefficient。请参阅 4.7 迁移指南。
13. 物理问题排查
按症状 → 原因与修复整理的速查表,涵盖穿透、摇晃的堆叠物体、缩放后的形状、瓦片碰撞颠簸、不稳定的圆柱体、物理死亡螺旋,以及远离原点时的浮点精度问题。
完整表格请参阅 references/troubleshooting.md。
14. 实施检查清单
- 动态刚体使用基本碰撞形状;凹形状仅用于 StaticBodies
- 在 Project Settings 中为碰撞层命名;为每个刚体正确设置层/遮罩
- 碰撞形状或刚体不设置
scale——直接使用形状大小参数 - RigidBodies 通过
_integrate_forces()修改状态,而非_physics_process() - 需要接触信号的 RigidBodies 设置
contact_monitor = true+max_contacts_reported > 0 - 移动平台使用
AnimatableBody2D/3D(而非手动移动的 StaticBody) - 代码中的射线检测仅在
_physics_process()内使用PhysicsDirectSpaceState - 启用物理插值;传送/初始放置后调用
reset_physics_interpolation() - 布娃娃骨骼使用与角色胶囊体不同的碰撞层
- 3D 项目使用 Jolt(Godot 4.6+ 中的非实验性默认选项)