Correct rotation on 1 axis only

Godot Version

4.4

Question

I’ve been working on a problem for 1 week, trying to find the angle needed to look towards a node, which I then apply to an animation key I’m playing. But it’s absolutely not working correctly, at first I thought I was doing the global to local conversion wrong, but after testing all the possibilities I could find via help, ia, and forums like reddit and godot, it still wasn’t working. What’s more, the camera’s x-axis rotation seemed to apply to the z-axis. Then I realized that rotation only works in a single case, if my player has rotated 90 degrees to the left from its original rotation point. I’m lost and I don’t understand. I’ll show you my code, a visual overview(Low quality otherwise impossible to upload), and the locations of the nodes I’m trying to rotate.


func set_animation_key() -> void:
	#Find rotation
	#var global_to_local_basis = PLAYER.NECK.global_transform.basis.inverse()
	
	var direction1 = (Global.monster.global_transform.origin - PLAYER.global_transform.origin).normalized()
	direction1 = direction1 * PLAYER.NECK.global_basis.inverse()
	var direction2 = (Global.monster.HEAD_MARKER.global_position - PLAYER.camera.global_transform.origin).normalized()
	direction2 = direction2 * PLAYER.camera.global_basis.inverse()
	
	#direction = global_to_local_basis * direction
	
	var target_rotation_neck = atan2(direction1.x, direction1.z)
	target_rotation_neck = Vector3(PLAYER.NECK.rotation.x, target_rotation_neck, PLAYER.NECK.rotation.z)
	var target_rotation_cam = atan2(direction2.y, direction2.z)
	target_rotation_cam = Vector3(target_rotation_cam, PLAYER.camera.rotation.y, PLAYER.camera.rotation.z)

	#Find track
	var animation_caught = PLAYER.ANIMATION_CAUGHT.get_animation("Caught")
	#var node_path_neck = "/CharacterBody3D/Neck"
	#var node_path_cam = PLAYER.camera.get_path_to(PLAYER,true)
	var track1 = 1 #animation_caught.find_track(node_path_neck ,Animation.TYPE_VALUE ) # or an integer
	var track2 = 0 #animation_caught.find_track(node_path_cam ,Animation.TYPE_VALUE )
	
	#Set key aniamtion
	animation_caught.track_set_key_value(track1, 0, PLAYER.NECK.rotation)
	animation_caught.track_set_key_value(track1, 1, target_rotation_neck)
	animation_caught.track_set_key_value(track2, 0, PLAYER.camera.rotation)
	animation_caught.track_set_key_value(track2, 1, target_rotation_cam)

Best to use a tween when you have to assign values at run time.

I think you could use Basis’ looking_at to get the target angles, if the math is what’s going wrong.

var direction2 := Global.monster.HEAD_MARKER.global_position - PLAYER.camera.global_position

var target_basis := Basis.looking_at(direction2)
var target_angles: Vector3 = target_basis.get_euler()

const duration = 1.0
var camera_tween := PLAYER.create_tween()
camera_tween.tween_property(PLAYER.NECK, "rotation:y", target_angles.y, duration)
camera_tween.tween_property(PLAYER.camera, "rotation:x", target_angles.x, duration)

Same outcome, the player turns but not towards the mob depending on his starting angle.

Is there anything else affecting the camera’s rotation? I notice it rolls (z-axis rotation) the first time in the video which shouldn’t happen given the tween code. I also notice your original sample was using the basis inverse which is strange on a already global coordinate vector.

With “tween”, the camera no longer turns on the z axis, but still doesn’t point exactly at the mob. And as for the “basis.invers()”, it’s because that’s what allowed me to get something as close as possible to what I wanted, otherwise it was worse. And I put it in to try out a bit of everything to see what I could come up with.

Could you add a debug shape to the HEAD_MARKER, ensure it’s in the correct place?

Yes, it’s the right position, I added a mesh as a child of HEAD_MARKER3D and the node follows the head well, and is in the right position in the game.

I’ve discovered something new, I’ve added a mesh that is placed on the calculated direction, the direction is good. The problem doesn’t come from there, so I came up with the idea of displaying the value of the target angle variable, then once the animation is complete, the player’s rotation, guess what! They’re different. The code is supposed to apply the value of the variable!

Exemple:
(0.0, 2.963429, 0.0)
(0.0, 0.172125, 0.0)

I’m discovering more and more strange things, when I display the value of the key previously modified, at the end of the animation and at the beginning, it displays the value of the target angle. The animation doesn’t seem to want to play this animation, and takes a value that seems random.

My bad i was printing the wrong rotation

I found the solution in the way I calculated the angle.


func set_animation_key() -> void:
	#Find rotation
	#var global_to_local_basis = PLAYER.NECK.global_transform.basis.inverse()
	
	var direction1 = (Global.monster.global_position - PLAYER.global_position).normalized()
	direction1 = direction1 * PLAYER.NECK.global_basis
	var direction2 = (Global.monster.HEAD_MARKER.global_position - PLAYER.camera.global_transform.origin).normalized()
	direction2 = direction2 * PLAYER.camera.global_basis
	
	#direction = global_to_local_basis * direction
	
	var target_rotation_neck = Basis.looking_at(direction1,Vector3.UP).get_euler()
	target_rotation_neck = Vector3(PLAYER.NECK.rotation.x, target_rotation_neck.y, PLAYER.NECK.rotation.z)
	var target_rotation_cam = Basis.looking_at(direction2,Vector3.UP).get_euler()
	target_rotation_cam = Vector3(target_rotation_cam.x, PLAYER.camera.rotation.y, PLAYER.camera.rotation.z)
	
	#Find track
	var animation_caught = PLAYER.ANIMATION_CAUGHT.get_animation("Caught")
	#var node_path_neck = "/CharacterBody3D/Neck"
	#var node_path_cam = PLAYER.camera.get_path_to(PLAYER,true)
	var track1 = 0 #animation_caught.find_track(node_path_neck ,Animation.TYPE_VALUE ) # or an integer
	var track2 = 1 #animation_caught.find_track(node_path_cam ,Animation.TYPE_VALUE )
	
	#Set key aniamtion
	animation_caught.track_set_key_value(track1, 0, PLAYER.NECK.rotation)
	animation_caught.track_set_key_value(track1, 1, target_rotation_neck)
	animation_caught.track_set_key_value(track2, 0, PLAYER.camera.rotation)
	animation_caught.track_set_key_value(track2, 1, target_rotation_cam)

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.