Getting CollisionShape3D from the collision result of intersect_ray

Godot Version

4.6

Question

Hello,

I am trying to get the CollisionShape3D that is hit when a get_world_3d().direct_space_state.intersect_rayis made.

The dictionary returned contains the collider key, which comes back to the RigidBody3D parent of the collider shape. The shapekey contains presumably an index to the shape that was hit in the CollisionShape3D. How do I reference this shape to the CollisionShape3D?

This is the function I am using to query:

func _send_ray_from_screen_to_world(screenPoint: Vector2) -> Dictionary:
	var from = camera.project_ray_origin(screenPoint)
	var to = from + camera.project_ray_normal(screenPoint) * ray_length
	var ray_query = PhysicsRayQueryParameters3D.create(from, to)
	var collision = get_world_3d().direct_space_state.intersect_ray(ray_query)
	
	return collision

The code I tried to use, which doesn’t populate collision_area:

	var collision = _send_ray_from_screen_to_world(event.position)
	var collided_rb : RigidBody3D = collision["collider"] as RigidBody3D
	var shape_id = collision["shape"]
	var shape_owner_id = collided_rb.shape_find_owner(shape_id)
	var collision_area : Shape3D = null
	if shape_owner_id != 0:
		# shape owner found
		collision_area = collided_rb.shape_owner_get_shape(shape_owner_id, shape_id) as Shape3D

Thanks!

I think I have managed to solve it. I think I got a bit confused.

The issue with the above code is that it tries to find Shape3D, not CollisionShape3D (which is what I want to get).

Additionally, there doesn’t seem to be a way to ask a Shape3D for its parent (probably as it is a Resource, not a Node).

The below code works to get the CollisionShape3D of a Shape3D from the Dictionary returned by get_world_3d().direct_space_state.intersect_ray:

	var collision = _send_ray_from_screen_to_world(event.position)
	var collided_rb : RigidBody3D = collision["collider"] as RigidBody3D
	if collision["shape"] == 0:
		return
	var shape_owner_id = collided_rb.shape_find_owner(collision["shape"])
	var collision_shape = collided_rb.shape_owner_get_owner(shape_owner_id) as CollisionShape3D

Though, I am not sure if there is an error path for CollisionShape3D.shape_owner_get_owner that I should be compensating for.

Looking at the C++ source code for CollisionObject3D - parent of CollisionShape3D (scene/3d/physics/collision_object_3d.cpp), it would only error if you passed in an invalid id, or if the shape does not have an owner (maybe if it has not been instanced as a part of a rigid body). I’ve added an if to be safe.