Hi, I am back again to ask for help with a little problem I have with my code.

I am trying to get the world position of my mouse instead of its viewport position, but anything I tried so far did not work. I tried using the raycast method in the documentation but I'm not sure I understand how to implement it completely.

I want to have it as simple as I can but I did not want to add too many unnecessary steps like with the canvas method since I do not have a canvas yet. (I do not know how to make a UI yet and I prefer adding stuff in steps ')

Anyways, my question is: Is there a way ,in 3D, I can use to transform my mouse position into world position from the _unhandled_input method without using a canvas?

My case is a little weird, since i am using a grid to place stuff in the world and would like to build to the closest grid position relative to the mouse's world position. That part I can figure out nicely I think, but it's the mouse world position that causes me problem '

I have this code currently: It is far from good and I reverted back to the code that at least returned the viewport position rather than some weird float value that didn't line up.

func _get_position_from_click(mouse_pos):
	var from = cam.project_ray_origin(mouse_pos)
	var to = from + cam.project_ray_normal(mouse_pos) * ray_length
	return to

func _unhandled_input(event):
	if event is InputEventMouseButton and event.button_index == BUTTON_LEFT:
		print(event.position)

Huge thank you in advance for your help!

Here, this code should work:

onready var camera = get_node("Camera")

func _physics_process(delta):
	if Input.is_action_just_released("click"):
		var world_pos = get_world_pos(get_viewport().get_mouse_position())
		print(world_pos)
		
func get_world_pos(mouse_pos):
	var ray_length = 1000
	var from = camera.project_ray_origin(mouse_pos)
	var to = from + camera.project_ray_normal(mouse_pos) * ray_length
	var space_state = get_world().get_direct_space_state()
	var result = space_state.intersect_ray(from, to)
	var world_pos = Vector3()
	if result.has("position"):
		world_pos = result.get("position")
	return world_pos

Note, that the objects in your scene need collision shapes for the ray cast to work. Otherwise the ray will hit nothing and be null (I check for this and return 0, 0, 0). If you are using a sky map or other geometry that doesn't have a collision shape, you can make a dummy static body, but honestly this might be fine as in these cases you wouldn't get a valid 3D point anyway.

Huge thank you for the help!

I'm curious, is it possible to force the z value or whichever axis is used for the up axis onto 0 as to only get the x and y position or would it still be null?

I really only need the target position without necessarily having a collision since my plan is to be able to place something in the "void" per say.

If not I could certainly just make an empty mesh with a collision plane with a size equal to the grid or bigger.

In any case, huge thank you again for your help, I will try it right after lunch.

Yes, if you don't need to collide with 3D objects, then you can just calculate the first part of the ray and use that. For example like this:

func get_void_pos(mouse_pos):
	var ray_length = 4
	var from = camera.project_ray_origin(mouse_pos)
	var to = from + camera.project_ray_normal(mouse_pos) * ray_length
	return to

Note, I use 4 as the ray length. This will result in your points being in a radius of 4 units away from the center of the camera (imagine like a sphere surrounding you).

Oh I see, huge thank you! You are the absolute best <3

Sorry to ask another thing, but could this thread be marked as a question so I can mark your answer as accepted please?

Sorry once again, I have a little question related to this again, will set_cull_mask_bit allow me to disable/enable specific layers to be interacted by the raycast?

The code you provided with the collision detection works flawlessly even without having objects in the world from what I have seen. But the only thing I have a problem with currently is that I am a little unsure if the cull mask bit function will allow me to control which layer is being detected.

Thank you in advance for your reply!

a year later