mcpField
P
physics-system

physics-system

github.com/jame581开发889169 次安装5 天前更新
代码仓库

关于 physics-system

面向 Godot 4.3+ 开发者的物理系统技能,讲解碰撞体、刚体、区域、查询与插值等实践,并涵盖 Jolt Physics 和布娃娃系统。

主要功能

  1. 01区分四类物理碰撞对象
  2. 02配置碰撞形状、层与遮罩
  3. 03通过射线和空间状态查询
  4. 04使用 Jolt Physics 进行 3D 物理
  5. 05设置物理插值与布娃娃

适用场景

  1. 01制作玩家、敌人与可交互物体的碰撞
  2. 02实现触发区域、重力区或音频区
  3. 03进行射线检测和 3D 鼠标拾取
  4. 04为角色制作布娃娃物理效果

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/jame581/godotprompter --skill physics-system

安装后在 Claude Code 中输入/physics-system确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
area-recipes.md
collision-layers.md
collision-shapes.md
interpolation-camera.md
interpolation-tuning.md
jolt-differences.md
ragdoll-recipes.md
raycasting-recipes.md
rigidbody-recipes.md
softbody-recipes.md
staticbody-recipes.md
troubleshooting.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 没有变化,升级后即可自动获得改进。

核心规则
  1. 将所有游戏逻辑移至 _physics_process()——在物理帧之外设置变换会导致抖动
  2. 移动物理对象的 Tween 和 AnimationPlayer 必须使用物理帧计时
  3. 传送或进行初始放置后调用 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+ 中的非实验性默认选项)

评论

支持 Markdown