godot-physics
Original:🇺🇸 English
Translated
Use Godot 4.x physics bodies and detection in 2D and 3D: RigidBody, StaticBody, Area, and CharacterBody; collision layers vs masks; contact/overlap signals; and raycasts (RayCast nodes and direct space-state queries). Use when configuring collision layers/masks, detecting overlaps with Area2D/Area3D, applying forces to a RigidBody, or casting rays in a Godot project (.tscn with physics bodies).
1installs
Added on
NPX Install
npx skill4agent add gamedev-skills/awesome-gamedev-agent-skills godot-physicsTags
Translated version includes tags in frontmatterSKILL.md Content
View Translation Comparison →Godot Physics (4.x, 2D + 3D)
Pick the right physics body, wire up collision layers/masks, detect overlaps, and cast
rays. Concepts apply to both 2D and 3D (swap the / suffix). Targets
Godot 4.3+.
2D3DWhen to use
- Use when choosing between body types, setting collision layers/masks so the right
things collide, detecting overlaps (triggers, hurtboxes) with , applying forces/impulses to a
Area, or casting rays for line-of-sight/ground checks.RigidBody
When not to use: kinematic character controllers () →
; tile collision setup → ; tuning the feel of physics
(timestep, mass, jitter) → .
move_and_slidegodot-2d-movementgodot-tilemapphysics-tuningCore workflow
- Choose the body type:
- — never moves (floors, walls). Collides, no simulation.
StaticBody - — fully simulated (gravity, forces, bouncing). Don't set its
RigidBodydirectly; apply forces/impulses or setposition.linear_velocity - — script-driven kinematic (see
CharacterBody).godot-2d-movement - — detects overlaps and can apply gravity/damping; no solid collision. Every body needs a
Area(orCollisionShape) child.CollisionPolygon
- Configure layers and masks. A body is on its layers and scans for its masks. Two bodies interact only if one's layer is in the other's mask. Name layers in Project Settings > Layer Names for clarity.
- Detect overlaps with signals (
Area,body_entered).area_entered - Drive RigidBodies with forces/impulses, or override for full control.
_integrate_forces - Cast rays with a node (polled each frame) or a one-shot space-state query from code.
RayCast2D/3D
Patterns
1. Collision layers vs masks (set from code)
gdscript
# Player is on layer 1, scans layers 2 (walls) and 3 (enemies).
func _ready() -> void:
set_collision_layer_value(1, true) # I am on layer 1
set_collision_mask_value(2, true) # I collide with things on layer 2
set_collision_mask_value(3, true) # ...and layer 3
# Bit-field forms also exist: collision_layer = 1; collision_mask = 0b1102. Area2D as a trigger / hurtbox
gdscript
extends Area2D # e.g. a damage zone
func _ready() -> void:
body_entered.connect(_on_body_entered)
area_entered.connect(_on_area_entered)
func _on_body_entered(body: Node2D) -> void:
if body.has_method("take_damage"):
body.take_damage(10)
func _on_area_entered(area: Area2D) -> void:
print("Overlapped area: ", area.name)3. Applying force and impulse to a RigidBody3D
gdscript
extends RigidBody3D
func push(direction: Vector3) -> void:
apply_central_impulse(direction * 8.0) # instantaneous velocity change
func _physics_process(_delta: float) -> void:
apply_central_force(Vector3.FORWARD * 4.0) # continuous force (per tick)
# Never set `position` on a RigidBody to move it; use forces/impulses or
# set linear_velocity. Use freeze=true if you must hold it in place.4. Raycast two ways
gdscript
# A) RayCast2D node: enable it, then poll after physics has updated.
@onready var ray: RayCast2D = $RayCast2D # set target_position in the editor
func _physics_process(_delta: float) -> void:
if ray.is_colliding():
var hit := ray.get_collider()
var point := ray.get_collision_point()
# B) One-shot query from code (no node needed).
func ground_under(global_from: Vector2) -> Dictionary:
var space := get_world_2d().direct_space_state
var query := PhysicsRayQueryParameters2D.create(global_from, global_from + Vector2(0, 64))
query.collision_mask = 1 # only layer 1
return space.intersect_ray(query) # {} if nothing hit, else collider/position/normalPitfalls
- Layer vs mask confusion is the #1 bug. Layer = "what I am"; mask = "what I look for". For A to detect B, B's layer must be in A's mask. Detection can be one-directional.
- Moving a RigidBody by fights the solver and causes tunneling/jitter. Use impulses/forces, set
position, orlinear_velocityit. To teleport, set position and zero the velocities insidefreeze._integrate_forces - doesn't fire when neither monitoring nor monitorable is set, or layers/masks don't overlap.
Areamust be on for the Area to detect;monitoringlets others detect it.monitorable - RayCast2D/3D read stale or no data if is false, or if you read it before physics updated — read in
enabled, and call_physics_processafter moving it within the same tick.force_raycast_update() - Forgetting a (or leaving it empty) means the body never collides.
CollisionShape - Fast objects tunnel through thin walls; enable continuous CD on the RigidBody
() or use a raycast-based check.
continuous_cd - excludes its own body? Pass
intersect_ray(anquery.exclude = [self.get_rid()], not an array of nodes) to skip self-hits.Array[RID]
References
- For , joints, one-way collision,
_integrate_forcesdirect access, shape queries (PhysicsServer), and 3Dintersect_shape, readmove_and_collide.references/bodies-and-queries.md
Related skills
- — kinematic
godot-2d-movementcontrollers.CharacterBody2D - — tile collision shapes and their layers.
godot-tilemap - — engine-agnostic feel: timestep, mass, drag, CCD.
physics-tuning - — 3D scene setup these bodies live in.
godot-3d-essentials