• 3D
  • Need Help Getting a 3D object to look_at the cursor position in 3D

I'm working on a game that is mechanically 2D, but for stylistic purposes I'm putting it in a 3D space. The first real problem I've run into is getting a character's arm to point at the cursor. After searching online this is the code I tried to use:

func _physics_process(delta):

var currentFrame = $Drawing/BaseSprite.frame

	#GETTING THE CURSOR POSITION
	var dropPlane  = Plane(Vector3(0, 0, 1), 0)
	var position3D = dropPlane.intersects_ray(
                             $Camera.project_ray_origin(get_viewport().get_mouse_position()),
                             $Camera.project_ray_normal(get_viewport().get_mouse_position()))
	var cursor3D = Vector3()
	cursor3D.x = position3D.x
	cursor3D.y = position3D.y
	cursor3D.z = self.translation.z
	
	#AIMING THE ARM
	$Drawing/ShootingArm.look_at(cursor3D,Vector3(0,0,1))

It almost works. Here's what I'm trying to do:

What I'm getting is off by about 45 degrees, and stretches the image out in a weird way:

The arm moves, but at that weird offset and with a weird stretch, so I'm thinking either the coordinates I'm getting are wrong, or I'm somehow passing a z coordinate that isn't in line with the arm, or I just fundamentally don't understand how look_at works. Any assistance would be great. Thanks.

I'll have to make a test project to know for sure, but I think the look_at function resets the scale of the node, which might be causing the stretch. I know that using the look_at function on a Transform object requires me to save the scale, call the function, and reapply the scale afterwards.

For the offset, the only thing I can think of is maybe the position of the plane is the problem? Maybe set the distance to the Z axis of the origin of the global transform of the node, so the plane's depth is at the same distance as the character?

Another thing that could, potentially, be causing the problem is the length of the raycast. Maybe it is not long enough to hit the plane, so the cursor3d variable's X and Y coordinates are zero. I do not think this is the issue, but it might be something to look into.

I'll try to make a test project and experiment a bit. (Side note: Welcome to the forums!)

cursor3D.z = self.translation.z are you sure this is right? You want to use the Player nodes translate.z? Also I think you might need to normalize the Cursor3D vector.

@TwistedTwigleg said: I'll have to make a test project to know for sure, but I think the look_at function resets the scale of the node, which might be causing the stretch. I know that using the look_at function on a Transform object requires me to save the scale, call the function, and reapply the scale afterwards.

This makes a lot of sense. I readjusted the code a little bit and it's no longer stretching, but huge. And thanks for welcoming me!

@Megalomaniak said: cursor3D.z = self.translation.z are you sure this is right? You want to use the Player nodes translate.z? Also I think you might need to normalize the Cursor3D vector.

The character moves along the X, so to keep things on the same depth, I need to keep the Z the same right? And forgive my newbie ignorance. I've done some game design and coding in the past, but 'normalizing' is a new concept to me. How would I implement that?

Also, I'm wondering if instead of using look_at(), I rotated the arm around the Z based on the angle between it and the point? My most recent code got a little closer, but I noticed the arm (at least the part it was considering the "front" which for some reason is the flat of the shoulder) would turn towards the screen. Here's the updated code:

var cursorPlane = Plane(Vector3(0,0,1), 0.5)

var cursor3D = cursorPlane.intersects_ray
						 ($Camera.project_ray_origin(get_viewport().get_mouse_position()),
	                                          $Camera.project_ray_normal(get_viewport().get_mouse_position()))

var lookPoint = Vector3(cursor3D.x, cursor3D.y, self.translation.z)

After some experimentation, I found a solution of sorts. I could not get the raycasting on the Plane object working without having the rotation act strangely. It seems the look_at function in Spatial nodes really does not like rotating on constrained axes.

After lots of fiddling and experimenting, I decided to move the calculations to 2D, since the problem is ultimately a 2D one, that needs to be applied to 3D. Using the look_at function from a Node2D node, and passing the calculated positions to it, I was able to successfully have the arm rotate towards the mouse cursor. :smiley:

Hopefully the project is helpful!

After some experimentation, I found a solution of sorts. I could not get the ray-casting on the Plane object working without having the rotation act strangely. It seems the look_at function in Spatial nodes really does not like rotating on constrained axes.

After lots of fiddling and experimenting, I decided to move the calculations to 2D, since the problem is ultimately a 2D one, that needs to be applied to 3D. Using the look_at function from a Node2D node, and passing the calculated positions to it, I was able to successfully have the arm rotate towards the mouse cursor. :smiley:

Here is a link to the project as a Google Drive download Hopefully the project is helpful!

This just might do it! Thanks! I'm so new I hadn't gotten to the point of mixing 2D nodes into a 3D scene. I'll plug this in and see how it goes.