From godot-prompter
Guides Godot 4.3+ physics systems: bodies, collision shapes, raycasting, areas, rigid bodies, ragdolls, soft bodies, Jolt physics, and interpolation via GDScript/C# examples.
How this skill is triggered — by the user, by Claude, or both
Slash command
/godot-prompter:physics-systemThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
All examples target Godot 4.3+ with no deprecated APIs. GDScript is shown first, then C#.
All examples target Godot 4.3+ with no deprecated APIs. GDScript is shown first, then C#.
Related skills: player-controller for CharacterBody2D/3D movement patterns, component-system for hitbox/hurtbox composition, godot-optimization for physics performance tuning, camera-system for camera follow and interpolation, multiplayer-sync for networked physics, 2d-essentials for tile collision setup and 2D canvas layers.
Four collision-object types (the last three extend PhysicsBody2D/3D):
| Type | Moved by | Use for |
|---|---|---|
Area2D/3D | Code | Overlap detection, gravity zones, audio zones |
StaticBody2D/3D | Not moved (or constant_linear_velocity) | Walls, floors, conveyor belts |
RigidBody2D/3D | Physics engine | Crates, projectiles, debris, ragdolls |
CharacterBody2D/3D | Code | Players, enemies, NPCs (see player-controller) |
Every collision object needs at least one CollisionShape2D/3D (or CollisionPolygon2D/3D) child. Jolt Physics is the default 3D engine since 4.4 (non-experimental from 4.6) — see Section 8. 2D always uses GodotPhysics.
Critical rule: NEVER scale collision shapes or physics bodies via
scale. Use the shape's own size parameters (radius, extents, height) — scaled shapes produce incorrect collision results.
| Method | Effect | When to use |
|---|---|---|
apply_force(force, position) | Continuous accel at point | Thrusters, wind, magnets |
apply_central_force(force) | Continuous accel at center | Gravity, constant push |
apply_impulse(impulse, position) | Instant velocity change at point | Bullet hit, explosion |
apply_central_impulse(impulse) | Instant velocity change at center | Jump, knockback |
apply_torque(torque) | Continuous angular accel | Steering, spinning |
apply_torque_impulse(impulse) | Instant angular velocity change | Impact spin |
See references/rigidbody-recipes.md for a worked thrust-and-spin example (GDScript + C#) using
apply_force+apply_central_impulse+apply_torque.
Use _integrate_forces(state) instead of _physics_process() when you need to read/modify a RigidBody's transform, velocity, or angular velocity. Setting position or linear_velocity directly in _physics_process() fights the physics engine.
Warning:
_integrate_forces()is NOT called while the body is sleeping. Setcan_sleep = falseif you need continuous callbacks; otherwise prefer letting bodies sleep for performance.
See references/rigidbody-recipes.md for the full thrust + torque example using
state.apply_force/state.apply_torque(GDScript + C#).
contact_monitor = true + max_contacts_reported > 0. Then body_entered/body_exited fire as expected.PhysicsMaterial resource controls friction (0 ice → 1 rubber) and bounce (0 → 1).FREEZE_MODE_STATIC (acts like a StaticBody) or FREEZE_MODE_KINEMATIC (code-moved, pushes others).look_at() a RigidBody — use _integrate_forces and set state.angular_velocity from a cross-product steering term.See references/rigidbody-recipes.md for full GDScript + C# recipes (contact handler with
take_damage, PhysicsMaterial property table, freeze toggle, RigidBody3D homing-via-angular-velocity).
StaticBody is not moved by the physics engine but can push other bodies via constant_linear_velocity (e.g. conveyor belts). For platforms that move via code AND push CharacterBodies, use AnimatableBody2D/3D — a plain StaticBody moved by code will not push CharacterBodies reliably.
See references/staticbody-recipes.md for the conveyor belt and moving-platform recipes (GDScript + C#, with Tween-driven AnimatableBody2D loop).
Areas detect overlaps and override physics properties within their bounds. They do NOT produce collision responses — bodies pass through them. Connect body_entered / body_exited for body overlaps; use area_entered / area_exited for Area-to-Area (hitbox vs hurtbox — see component-system). Areas can also override gravity (zero-G zones, point gravity / black holes), linear_damp / angular_damp (water, slow-mo), and redirect audio to a specific AudioBus. When multiple areas overlap, priority decides order; pick a space_override mode (COMBINE, REPLACE, COMBINE_REPLACE, REPLACE_COMBINE).
See references/area-recipes.md for the GDScript + C# overlap-detection canonical example, the space-override mode reference table, and zero-G + point-gravity recipes.
| Shape (2D / 3D) | Use case |
|---|---|
Rectangle / Box | Crates, platforms, rooms |
Circle / Sphere | Balls, projectiles, simple characters, trigger zones |
Capsule (2D & 3D) | Characters — rounded, slides over edges |
Segment2D / — | Thin walls, laser beams |
SeparationRay2D / — | Character ground snapping |
WorldBoundary2D / — | Infinite floor/wall/ceiling |
— / Cylinder3D | Pillars, barrels (Jolt only — unstable on GodotPhysics) |
| Type | Usable with | Cost | Notes |
|---|---|---|---|
| Primitive | All bodies | Cheapest | Always prefer for dynamic bodies |
ConvexPolygonShape | All bodies | Fast | No holes or inward curves |
ConcavePolygonShape | StaticBody only | Slowest | Accurate for level geometry; no volume |
Generate shapes: for 3D, MeshInstance3D → Mesh menu → Create Single Convex / Multiple Convex (V-HACD) / Trimesh (ConcavePolygonShape). For 2D, Sprite2D → Sprite2D menu → Create CollisionPolygon2D Sibling (adjust Simplification / Shrink / Grow).
Favor primitives for dynamic bodies; minimize shape count per body (each costs narrow-phase checks); never translate/rotate/scale CollisionShape nodes — a single non-transformed shape enables broad-phase optimization; concave shapes only on StaticBodies (O(n) triangle checks); multiple shapes on one body don't collide with each other (this is correct, not a bug); shapes must be direct children — indirect children are ignored.
Godot provides 32 physics layers per dimension (2D and 3D separately).
Mental model: Layer = "I am", Mask = "I scan for". A collision happens when object A's mask includes object B's layer, OR vice versa.
Project Settings → Layer Names → 2D Physics (or 3D Physics). Typical layer set: Player / Enemy / World / Projectile / Pickup / Trigger.
Use set_collision_layer_value(N, true) / set_collision_mask_value(N, true) (1-indexed) for readable code, or shorthand bitmasks collision_mask = (1 << 2) | (1 << 4) (layers 3 and 5). Expose layer selection in the Inspector via @export_flags_2d_physics var scan_layers: int = 0 (GDScript) or [Export(PropertyHint.Layers2DPhysics)] (C#).
collision_layer = 0
set_collision_layer_value(1, true) # Add to layer 1 (Player)
collision_mask = 0
set_collision_mask_value(3, true) # Scan layer 3 (World)
CollisionLayer = 0;
SetCollisionLayerValue(1, true);
CollisionMask = 0;
SetCollisionMaskValue(3, true);
Add a RayCast2D / RayCast3D as a child node — it casts every physics frame automatically. Read with is_colliding() and get_collider() / get_collision_point() / get_collision_normal().
@onready var ray: RayCast2D = $RayCast2D
func _physics_process(_delta: float) -> void:
if ray.is_colliding():
var collider := ray.get_collider()
var point := ray.get_collision_point()
private RayCast2D _ray;
public override void _Ready() => _ray = GetNode<RayCast2D>("RayCast2D");
public override void _PhysicsProcess(double delta)
{
if (_ray.IsColliding())
{
var collider = _ray.GetCollider();
var point = _ray.GetCollisionPoint();
}
}
For on-demand queries, access the space state via get_world_2d().direct_space_state (or get_world_3d()) and call intersect_ray(query) with PhysicsRayQueryParameters2D/3D.create(from, to). Set query.exclude = [get_rid()] to skip self, query.collision_mask to filter layers. Only safe inside _physics_process() — the physics space is locked during rendering.
See references/raycasting-recipes.md for the full GDScript + C# code-based raycast example with self-exclusion and mask filtering, plus the 3D mouse-picking recipe.
The intersect_ray result dictionary contains position, normal, collider, collider_id, rid, shape. PhysicsDirectSpaceState also supports intersect_point (overlapping shapes at a point), intersect_shape (area query), cast_motion (shape sweep), collide_shape (contact points), get_rest_info (resting collision info). For 3D mouse picking, Camera3D.project_ray_origin(screen_pos) + project_ray_normal(screen_pos) builds the ray.
See references/raycasting-recipes.md for the full mouse-picking recipe (GDScript + C#).
Jolt is a built-in alternative physics engine available since Godot 4.4. It is the default for new 3D projects starting in 4.4. (Godot 4.6+) Jolt is no longer marked experimental and is the confirmed stable default for all new 3D projects.
Note: Godot 4.6 is in beta; verify behavior on stable release.
Project Settings → Physics → 3D → Physics Engine → Jolt Physics → Save → Restart editor. (3D only; 2D always uses GodotPhysics.)
Wins: better stacking stability, reliable CylinderShape3D, better SoftBody3D, optional thread-safe mode, active-edge detection (fixes ghost collisions). Differences from GodotPhysics: position-only Baumgarte stabilization, convex-radius collision margins, single-body joints treat the unassigned slot as node_a (world — opposite of GodotPhysics), face_index returns -1 unless Enable Ray Cast Face Index is on, and some joint properties (bias, softness, relaxation, damping) are unsupported on PinJoint / HingeJoint / SliderJoint / ConeTwistJoint.
Smooths visual motion between physics ticks, eliminating "staircase" jitter when tick rate ≠ frame rate. Enable in Project Settings → Physics → Common → Physics Interpolation. Godot 4.5+ restructured the 3D interpolation pipeline (RenderingServer → SceneTree) for more accurate results in nested transforms — no API change, automatic improvement on upgrade.
_physics_process() — transforms set outside physics ticks cause jitterreset_physics_interpolation() after teleporting or initial placement to prevent "streaking"func teleport_to(pos: Vector2) -> void:
global_position = pos
reset_physics_interpolation()
public void TeleportTo(Vector2 pos)
{
GlobalPosition = pos;
ResetPhysicsInterpolation();
}
node.physics_interpolation_mode accepts PHYSICS_INTERPOLATION_MODE_INHERIT (default), _ON, or _OFF. Tick rate (Project Settings → Physics → Common → Physics Ticks per Second): 10–30 TPS for slow/turn-based, 30–60 (60 default) for most games, 60+ for fast-paced/racing/precision platformers. Temporarily set 10 TPS during dev to surface interpolation problems.
Cameras need special handling under physics interpolation. Make the camera independent (or top_level = true), update it in _process() (not _physics_process()), and read the target's smooth position with get_global_transform_interpolated().
See references/interpolation-camera.md for the full smooth-follow Camera3D recipe (GDScript + C#).
Ragdolls replace animation with physics for procedural death, explosions, or limp characters. Generate via Skeleton3D → Skeleton menu → Create Physical Skeleton. Use ConeJoint for shoulders/hips/neck, HingeJoint for elbows/knees — PinJoint (default) tends to crumple. Drive via physical_bones_start_simulation(), blend with Influence.
See references/ragdoll-recipes.md for setup, joint guidance, full GDScript + C# control, animation blending, and collision exceptions.
SoftBody3D simulates deformable objects (cloth, capes, jelly). Mesh subdivision drives the simulation; no CollisionShape child needed. Jolt Physics recommended. Set Simulation Precision ≥ 5 to prevent collapse. Pressure > 0.0 only on closed meshes.
Godot 4.5+ adds apply_central_impulse() / apply_central_force() for RigidBody3D-style force application — distributes across all simulation points.
See references/softbody-recipes.md for the cloth/cape walk-through (PlaneMesh, BoneAttachment3D pinning, Parent Collision Ignore) and the 4.5+ force/impulse API with GDScript and C# (explosion knockback, continuous wind).
| Symptom | Causes & fixes |
|---|---|
| Tunneling (fast objects pass through) | continuous_cd = true on RigidBody; thicken static colliders; raise tick rate (120–240 TPS) |
| Stacked objects wobble | Raise tick rate; switch to Jolt (3D) for much better stacking |
| Scaled shapes don't collide | Never use scale on bodies/shapes — set shape parameters directly (radius, extents). For shared shapes, shape.duplicate() to Make Unique |
| Tile collision bumps | 4.5+: TileMapLayer auto-merges via Physics Quadrant Size (default 16). Pre-4.5: manual composite colliders |
| CylinderShape3D unstable | Use Jolt (fully supported), or substitute CapsuleShape3D/BoxShape3D with GodotPhysics |
| Physics spiral of death | Engine can't finish in one frame — raise Max Physics Steps per Frame, reduce TPS, or cut body count |
| Unreliable far from origin | Float precision degrades past ~4 km. Use precision=double build or origin-shifting for planetary-scale games |
scale on collision shapes or bodies — use shape size parameters directly_integrate_forces(), not _physics_process()contact_monitor = true + max_contacts_reported > 0AnimatableBody2D/3D (not manually moved StaticBody)PhysicsDirectSpaceState inside _physics_process() onlyreset_physics_interpolation() called after teleport / initial placementnpx claudepluginhub jame581/godotprompter --plugin godot-prompterUnity 6 physics development guide. Use when working with Rigidbody, colliders, raycasting, triggers, collisions, joints, or physics simulation. Covers PhysX 5 (3D) and Box2D (2D) physics, FixedUpdate timing, layer masks, and contact data. Based on Unity 6.3 LTS documentation.
Composes Godot 3D scenes with sound Node3D structure, cameras, physics bodies, environment ownership, and 3D performance patterns.
Guide to implementing player movement in Godot 4.3+ using CharacterBody patterns, input handling, physics, and common movement recipes.