Now liveThe Skillselion MCP - thousands of ranked skills, loaded into your agent mid-task. No install.Get it →
thedivergentai avatar

Godot Raycasting Queries

  • 107 installs
  • 454 repo stars
  • Updated July 28, 2026
  • thedivergentai/gd-agentic-skills

Helps with ai & agent building tasks during AI-assisted development.

About

godot-raycasting-queries is a Claude Code skill for ai & agent building. It helps solo builders move faster with AI-assisted coding.

  • godot-raycasting-queries
  • AI & Agent Building
  • AI-coding skill

Godot Raycasting Queries by the numbers

  • 107 all-time installs (skills.sh)
  • +18 installs in the week ending Aug 5, 2026 (Skillselion tracking)
  • Ranked #4,145 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
  • Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/thedivergentai/gd-agentic-skills --skill godot-raycasting-queries

Add your badge

Show developers this skill is listed on Skillselion. Paste this into your README.

Listed on Skillselion
Installs107
repo stars454
Last updatedJuly 28, 2026
Repositorythedivergentai/gd-agentic-skills

What it does

Helps with ai & agent building tasks during AI-assisted development.

Files

SKILL.mdMarkdownGitHub ↗

Raycasting and Physics Queries

Physics queries allow for instantaneous detection of objects using lines (rays), volumes (shapes), or points.

Available Scripts

direct_space_state_raycast.gd

Expert usage of PhysicsDirectSpaceState2D/3D for bypassing node-based overhead in high-frequency queries.

shapecast_ground_detection.gd

Reliable ground/footing detection using volume-based ShapeCast instead of thin rays.

multiple_hit_piercing_ray.gd

Implementing piercing projectiles that detect and return multiple hits in a single line.

field_of_view_scanner.gd

AI sensor logic using a fan of raycasts to detect targets within a FOV cone.

raycast_reflection_logic.gd

Calculating bounces for lasers or bullets using collision normal reflection.

point_in_shape_query.gd

Checking for overlapping physics bodies at a single point (Explosion epicenters).

rest_info_3d_stuck_fix.gd

Using get_rest_info to detect stuck objects and resolve overlaps immediately.

mouse_pick_3d_query.gd

Converting 2D screen coordinates to 3D world rays for point-and-click interaction.

water_buoyancy_surface_calc.gd

Finding water surface height for buoyancy systems using high-to-low raycasting.

query_exclusion_optimization.gd

Optimizing performance by excluding specific RIDs (Resource IDs) from intersection checks.

NEVER Do in Physics Queries

  • NEVER access `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].
  • NEVER use ShapeCast when a thin RayCast is sufficient — Volume queries are significantly more expensive. Default to rays unless you need volumetric detection [3, 4].
  • NEVER assume results return `CollisionObject` nodes — CSG shapes, GridMap, and TileMapLayer return themselves, not a generic physics body [5, 6].
  • NEVER assume `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].
  • NEVER use complex visual meshes for physics queries — GPU-only data requires expensive thread locking to parse. Use simplified primitive collision shapes [10, 11].
  • NEVER iterate results to find the first valid hit — Use collision_mask and collision_layer to filter queries at the server level for maximum performance.
  • NEVER forget to exclude the caster — A ray starting from the center of a character will hit the character itself. Use query.exclude = [self.get_rid()] [20].
  • NEVER use rays for small, fast detection areas — Rays can "tunnel" through thin walls if the frame rate drops. Use cast_motion or high-frequency stepping for bullets.
  • NEVER query 1000+ rays individually in GDScript — Batch your queries or use the PhysicsServer directly in C++ if you reach extreme query counts.
  • NEVER ignore the `result.rid` — RIDs are the fastest way to identify and exclude objects in subsequent queries, bypassing node-path lookups [20].

---

3D Mouse Picking Example

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

---

Expert Raycasting & Query Architectures

1. NavMesh-Ray-Constrain (Line-of-Sight via NavMesh)

Standard physics raycasts check against collision shapes, but if using NavigationObstacle3D with carve_navigation_mesh enabled, the NavMesh dynamically adapts. To check LOS strictly against the NavMesh (avoiding carved holes), query an optimized path between points. If the result contains exactly 2 points, it's a direct, unobstructed line.

class_name NavMeshRayValidator extends Node
## Validates line-of-sight using NavigationServer3D path optimization.

@export var agent: NavigationAgent3D

## Returns true if there is a direct, unobstructed line-of-sight on the NavMesh.
func has_navmesh_line_of_sight(target_position: Vector3) -> bool:
    if not is_instance_valid(agent): return false
        
    var map: RID = agent.get_navigation_map()
    var start_position: Vector3 = agent.global_position
    
    # Query an optimized path using the funnel algorithm.
    var path: PackedVector3Array = NavigationServer3D.map_get_path(
        map, start_position, target_position, true, agent.navigation_layers
    )
    
    # A direct line of sight will yield exactly two points: start and end.
    return path.size() == 2

2. Collision-Object-Metadata (Decoupled Surface Types)

Instead of checking groups or names on intersect_ray() results, utilize Godot's built-in Object metadata. Attach arbitrary Variant data (e.g., "Stone", "Metal") to StaticBody3D nodes. This decouples the physics query from specific class implementations and allows for highly extensible surface interaction logic.

class_name SurfaceRaycaster extends Node3D
## Extracts surface metadata from raycast colliders for decoupled logic.

func perform_surface_raycast() -> void:
    var space_state := get_world_3d().direct_space_state
    var query := PhysicsRayQueryParameters3D.create(global_position, target_pos)
    var result: Dictionary = space_state.intersect_ray(query)
    
    if not result.is_empty():
        var collider: Object = result.collider
        var surface: StringName = &"default"
        
        # Check for explicitly assigned surface metadata.
        if collider.has_meta(&"surface_type"):
            surface = collider.get_meta(&"surface_type")
            
        print_rich("[color=cyan]Hit surface: %s[/color]" % surface)

3. Compute-Shader-Raycast (Massively Parallel Hits)

When performing tens of thousands of rays (Radar, GI, or Volumetrics), CPU-bound queries bottleneck. Use the RenderingDevice API to execute GLSL compute shaders. Note: Since the physics BVH is CPU-bound, world geometry must be serialized into a GPU storage buffer to perform ray-triangle intersections in GLSL.

class_name ComputeRaycaster extends Node
## Orchestrates massively parallel raycasts using the RenderingDevice API.

var _rd: RenderingDevice
var _shader: RID
var _pipeline: RID

func _ready() -> void:
    _rd = RenderingServer.get_rendering_device()
    var shader_file: RDShaderFile = load("res://compute_raycast.glsl")
    var spirv: RDShaderSPIRV = shader_file.get_spirv()
    _shader = _rd.shader_create_from_spirv(spirv)
    _pipeline = _rd.compute_pipeline_create(_shader)

func dispatch_rays(data_bytes: PackedByteArray) -> PackedByteArray:
    var buffer_rid: RID = _rd.storage_buffer_create(data_bytes.size(), data_bytes)
    var uniform := RDUniform.new()
    uniform.uniform_type = RenderingDevice.UNIFORM_TYPE_STORAGE_BUFFER
    uniform.binding = 0
    uniform.add_id(buffer_rid)
    
    var uniform_set: RID = _rd.uniform_set_create([uniform], _shader, 0)
    var compute_list: int = _rd.compute_list_begin()
    _rd.compute_list_bind_compute_pipeline(compute_list, _pipeline)
    _rd.compute_list_bind_uniform_set(compute_list, uniform_set, 0)
    _rd.compute_list_dispatch(compute_list, 1, 1, 1) 
    _rd.compute_list_end()
    _rd.submit()
    _rd.sync()
    
    var output: PackedByteArray = _rd.buffer_get_data(buffer_rid)
    _rd.free_rid(buffer_rid)
    return output

Reference

Related

  • godot-2d-physics, godot-physics-3d
  • Master Skill: godot-master

Related skills

This week in AI coding

Five minutes, every Monday - the tools, releases and tactics for developers.

unsubscribe anytime.