thedivergentai/godot-raycasting-queries
Expert blueprint for physics queries using RayCast, ShapeCast, and DirectSpaceState. Covers hit detection, volume overlap, mouse picking, and high-performance server-side intersection queries. Use when implementing projectiles, LOS, terrain grounding, or AI sensors. Keywords raycast, shapecast, direct_space_state, intersect_ray, intersect_shape, PhysicsRayQueryParameters, collision mask, mouse picking.
npx skills add https://github.com/thedivergentai/GD-Agentic-Skills --skill godot-raycasting-queries
Physics queries allow for instantaneous detection of objects using lines (rays), volumes (shapes), or points.
> MANDATORY for common paths — read before implementing (do not improvise query APIs from memory):
> - direct_space_state_raycast.gd — high-frequency intersect_ray without RayCast nodes.
> - query_exclusion_optimization.gd — RID exclude lists so casters never self-hit.
> - shapecast_ground_detection.gd — footing / volume casts when thin rays tunnel or miss.
>
> Do NOT Load every script below for one task. Open only the row that matches the decision table.
Expert usage of PhysicsDirectSpaceState2D/3D for bypassing node-based overhead in high-frequency queries.
Reliable ground/footing detection using volume-based ShapeCast instead of thin rays.
Implementing piercing projectiles that detect and return multiple hits in a single line.
AI sensor logic using a fan of raycasts to detect targets within a FOV cone.
Calculating bounces for lasers or bullets using collision normal reflection.
Checking for overlapping physics bodies at a single point (Explosion epicenters).
Using get_rest_info to detect stuck objects and resolve overlaps immediately.
Converting 2D screen coordinates to 3D world rays for point-and-click interaction.
Finding water surface height for buoyancy systems using high-to-low raycasting.
Optimizing performance by excluding specific RIDs (Resource IDs) from intersection checks.
direct_space_state outside of _physics_process() — The physics space can be locked or running on a separate thread; querying it in _process() is unsafe [1, 2].CollisionObject nodes — CSG shapes, GridMap, and TileMapLayer return themselves, not a generic physics body [5, 6].RayCast nodes update instantly — They update once per physics frame. If you move a node and query it immediately, you MUST call force_raycast_update() [3, 9].collision_mask and collision_layer to filter queries at the server level for maximum performance.query.exclude = [self.get_rid()] [20].cast_motion or high-frequency stepping for bullets.PhysicsServer directly in C++ if you reach extreme query counts.result.rid — RIDs are the fastest way to identify and exclude objects in subsequent queries, bypassing node-path lookups [20].Pick the cheapest API that answers the question. Always pair rays/shapes with RID exclude + masks (query_exclusion_optimization.gd).
| Need | Prefer | Cost | When | Script |
|------|--------|------|------|--------|
| Persistent sensor in the scene (ledge, aim assist debug) | RayCast2D/RayCast3D node | Low–med | Few casts; OK waiting one physics frame (or force_raycast_update()) | Scene node + NEVER rules |
| Hitscan / LOS / one-shot mid-frame ray | PhysicsDirectSpaceState*.intersect_ray | Low | High frequency, no permanent node | MANDATORY direct_space_state_raycast.gd |
| Footing, thick walls, melee volume | ShapeCast* / intersect_shape | Med–high | Thin ray tunnels or misses volume | MANDATORY shapecast_ground_detection.gd |
| Explosion / occupancy at a point | intersect_point | Low–med | Epicenter overlap list | point_in_shape_query.gd |
| Stuck / penetration resolve | get_rest_info | Med | Overlap recovery | rest_info_3d_stuck_fix.gd |
| Pierce / multi-hit along a line | Repeated intersect_ray + exclude RIDs | Med | Projectiles that keep going | multiple_hit_piercing_ray.gd |
| Screen → world click | Camera project + intersect_ray | Low | Picking | mouse_pick_3d_query.gd |
func screen_point_to_ray():
var space_state = get_world_3d().direct_space_state
var mouse_pos = get_viewport().get_mouse_position()
var origin = project_ray_origin(mouse_pos)
var end = origin + project_ray_normal(mouse_pos) * 2000
var query = PhysicsRayQueryParameters3D.create(origin, end)
var result = space_state.intersect_ray(query)
if result:
return result.collider
return null
direct_space_state in _physics_process, not _process.query.exclude = [get_rid()] on rays from character center.path.size() == 2 on NavigationServer3D.map_get_path for strict mesh LOS (see deep dive).collider.get_meta(&"surface_type") beats class/group checks for decals/footsteps.intersect_ray.NavMesh LOS validator, surface metadata, picking baseline, tunneling notes — references/query-elite-patterns.md.
> Progressive disclosure: open Official Documentation links only when researching a specific API;
> load Related Skills when routing work to a peer domain — do not preload the whole lattice.
RayCast* vs PhysicsDirectSpaceState* queries, result dictionaries, and exclude to avoid self-hits.intersect_ray / intersect_shape / intersect_point / get_rest_info / cast_motion contracts for mid-frame space queries.hit_from_inside, and collide-with flags for reusable ray parameter objects.force_raycast_update() is required after moving.force_shapecast_update() for footing/melee detection that thin rays miss.project_ray_origin / project_ray_normal for screen-to-world picking rays from the active camera._physics_process-only space access are language-level contracts this skill depends on.RayCast2D nodes vs direct space state for sensors.Take thedivergentai/godot-raycasting-queries from the repository into ~/.claude/skills for personal
use, or into .claude/skills inside a project.
The agent identifies a skill by the name field in its header. Two skills with the
same name cannot sit side by side — one of them will be ignored.