How to get location of intersect from raycast in 3D?

Godot Version

4.5 Stable

Question

Using the following code:

func raycast_check_for_card_3d(mouse : Vector2) → Variant:
    var space_state : PhysicsDirectSpaceState3D = get_world_3d().direct_space_state

    var start : Vector3 = get_viewport().get_camera_3d().project_ray_origin(mouse)
    var end : Vector3 = get_viewport().get_camera_3d().project_position(mouse, DIST)

    var params : PhysicsRayQueryParameters3D = PhysicsRayQueryParameters3D.new()

    params.from = start
    params.to = end
    params.exclude = exclude_list

    var result : Dictionary = space_state.intersect_ray(params)
    if result.size() > 0:
	    print(result)
	    return result
    else:
	    return null

If successful when called, gives a Raycast which hits a collision enabled node and returns the following information:

{ “position”: (-0.22431, -0.431095, -0.002769), “normal”: (0.0, 1.0, 0.0), “face_index”: -1, “collider_id”: 26759660956, “collider”: CollideyMcColliderFace:<RigidBody3D#26759660956>, “shape”: 0, “rid”: RID(446676598784) }

These keys can be accessed such as result.collider.name and the node can even be moved such as setting result.collider.position = new_position, and you can use append_array() to add [results.rid] to a variable exclude_list so that the ray ignores it on subsequent calls and continues until it hits a new collision body or so it gets ignored by other raycasts.

exclude_list.append_array([result.rid])

However, what is not clear, is how to obtain the location of the raycast’s hit for uses such as sending a node to that position.

For my specific usecase I am trying to drag a 3D card around hover above an invisible 3D thin box which is located at y=-0.2 by setting the position of the collider to the a Vector3(new_position.x, 0, new_position.y). Another much jankier solution is to calculate how many ingame meters it takes for the object to reach the edge of the screen multiplied by the ratio of the mouse position gotten with a mousemove’s event.position and then minus half the meter width, clamped to keep it in bounds, but it doesn’t look great.

P.S. sorry if my understanding / explanation is lacking, I had to figure this all out mostly on my own as the documentation completely lacks examples for 3D and is very difficult for beginners to parse, but most of what I mentioned here is mentioned in the RayCasting section of the documention if not the respective methods documentations.

EDIT: Another even more jankier solution, perhaps the jankiest, would be to make a huge grid of collision bodies and snap the card to them as needed.

I’m not really sure what the exact problem is. Is it your approach that seems “janky” or is it…

From what I’m reading in your post, you know how to access the data in the result. How is retrieving the position from the result not possible? Something tells me your understanding of raycasts and their utility is not correct.

Just so I know my understanding is correct, you’re trying to move a card to the point where a ray intersects with a collider, right? You should just be able to set the position of the card directly based on the result:

card.global_position = result.position

Perhaps you could elaborate on your own understanding of raycasts? I want to help but I’m not sure what the problem is from your point of view.

1 Like

Lmao no you don’t need to get the global position, I already elaborated that you can set the result.collider.position

Also the position returned by the raycast is the position at the center of the collider, it does not change no matter where you click on that collider. If the collider doesn’t move then it’s a static point.

That’s why my edit shared the positively bonkers idea of a grid of colliders at different positions.

EDIT: Ah wait, no, that position IS the position of impact, I was printing the result.collider.position instead of result.position HAHAHA~

1 Like