Yeah, shapes can collide at multiple points so it can’t give you a single collision point.
Then I think you’re left with the multiple ray casts method. I do something like this:
func get_entities_in_line_of_sight(from: Vector3, to: Vector3, exclude: Array[RID] = []) -> Array[Node3D]:
const MAX_COLLISIONS: int = 20
var entities: Array[Node3D] = []
var world_state: PhysicsDirectSpaceState3D = get_world_3d().get_direct_space_state()
for i in MAX_COLLISIONS:
var query := PhysicsRayQueryParameters3D.create(from, to)
query.set_exclude(exclude)
var result: Dictionary = world_state.intersect_ray(query)
if result:
entities.append(result.collider)
exclude.append(result.rid)
from = result.position
else:
break
return entities