RayCasting 3D from Camera

Godot Version

4.2

Question

Hi there, hopefully one kind soul can make me understand this…
I am trying to detect objects from a Camara3D to any object over a static 3d mesh…

In the documentation I have this, and it works, but, honestly it is not intuitive for me at all, I am not very smart… :wink:

func _physics_process(delta):
var space_state = get_world_3d().direct_space_state
var cam = $Camera3D
var mousepos = get_viewport().get_mouse_position()

var origin = cam.project_ray_origin(mousepos)
var end = origin + cam.project_ray_normal(mousepos) * RAY_LENGTH
var query = PhysicsRayQueryParameters3D.create(origin, end)
query.collide_with_areas = true

var result = space_state.intersect_ray(query)

My intuition is to add a RayCast3D to the Camera3D and manipulate its target_position following the mouse position, does it have any sense?

extends Camera3D

func _process(delta):
var mousePos=get_viewport().get_mouse_position()
var from=project_ray_origin(mousePos)
var to=from+project_ray_normal(mousePos)
$Ray.target_position=Vector3(to.x, to.y, 10.0)… I changed the Z value which is the direction target_position uses instead Y…

this is not working and I’d like to know why, to understand that I have to use the non-intuitive way for me… :wink:

Thanks in advance

You can use a RayCast3D node just fine. It’s a lot easier to understand. Check you have collision layers and masks all set right.

Maybe explain what you mean by “it’s not working.”

Also, please format your code with the </> tool. Always give us enough info to help.

1 Like

First, thanks a lot for your answer, sorry I didn’t know this tool for the code… :wink:

using Camera3D

func _process(delta):
	var mousePos=get_viewport().get_mouse_position()
	var from=project_ray_origin(mousePos)
	var to=from+project_ray_normal(mousePos)*10
	$Ray.target_position=Vector3(to.x, to.y, -5.0)
	$"../Log2".text=str($Ray.target_position)
	
	if $Ray.is_colliding():
		$"../log".text=$Ray.get_collider()

I have a good setup, in fact the Ray detects the ground and a box I have, but not exactly when I am over them but in a different place in the viewport, for me looks like is the Z value of $Ray.target_position but I can’t understand why… :wink:

using Camera3D

func _process(delta):
  var mousePos=get_viewport().get_mouse_position()
  $Ray.target_position.x = mousePos.x
  $Ray.target_position.y = mousePos.y

  print($Ray.target_position) # watch the output to see this
	
  if $Ray.is_colliding(): print("Hit ", $Ray.get_collider())

You will have to play with the scaling of the mouse position versus the viewport and the world, but that should get you started.

In the 3D view, make your ray go out from the camera a few meters.

1 Like

Thanks, is pretty the same I was trying to do, for 3D you have to play with negative Z in $Ray.target_position… but it does not seem to be an useful practice… if you have to look approaches for this to work, did you try it and make it work?