I've been trying to make a top-down game where the character faces towards the position of the mouse. I searched online and I figured out I have to use raycasting. More specifically, I implemented the following code:

``````func _input(event):
if event is InputEventMouseMotion:
var from = camera.project_ray_origin(event.position)
var to = from + camera.project_ray_normal(event.position) * ray_length
\$player.look_at(to*Vector3(1,0,1), from)
``````

where player is the character in question and raylength is the distance travelled by the ray. It is worth noting that 'player' is a separate scene made up of a KinematicBody and a mesh.
Though everything works as expected when the player is in the middle, everything starts malfunctioning when I move the player using move
and_slide(). This is when the object stops rotating fully in a circle.

What am I doing wrong?

in Engine

Just tried this and it works way better than the raycast method:

``````func _physics_process(delta):
var offset = -PI * 0.5
var screen_pos = get_viewport().get_camera().unproject_position(player.global_transform.origin)
var mouse_pos = get_viewport().get_mouse_position()
var angle = screen_pos.angle_to_point(mouse_pos)
player.rotation.y = -angle + offset
``````

Raycasting requires physics bodies, if no bodies are present then it would not work anymore.

by (4,246 points)
selected

Wow, that works!

It looks very complicated, though. I do not know how I was supposed to come up with that solution :)
Anyway, it works better than expected, because it works even when the camera is not facing top-down in a 90 degree angle to the floor. Kudos!

Dunno how I came up with that, but it's exactly how you handle it in a 2D top-down shooter with the only extra step is to unproject the player position from 3D to 2D, not that complicated.

Before that, I also worked on a 3D top-down shooter with raycasting for mouse handling so I know it doesn't work very well.

First, if you want to update something in realtime it is better to use the `_process` function and if you have to move a physical object, like a KinematicBody, `_physics_process`.

Second, if I remember correctly, to orient a node in the direction of the mouse is to start with `get_local_mouse_position` (Doc). And the rotation is calculated with something like `Vector2(-mouse_vec.y, mouse_vec.x).angle()`.

by (1,049 points)

This is in 3D, `get_local_mouse_position()` is only available for 2D nodes. Call `get_viewport().get_mouse_position()` for global position and subtract the node position to get the local mouse position.