Erratic rotation when trying to use rotation tween

Godot Version

Godot 4.3

Question

`I’m trying to have the players arm rotate into position when aiming down sights, and the tweens for changing the arms position work fine, but the rotational tweens make the arm rotate randomly. Here is the code for the tweens, the constants are the position and rotation of the arm object in the editor:

const GUN_X = 0.388
const GUN_Y = -0.21
const GUN_Z = 0.467
const AIM_X = -0.14
const AIM_Y = -0.093
const AIM_Z = 0.571

const GUNROT_X = 0
const GUNROT_Y = 177.1
const GUNROT_Z = 0
const AIMROT_X = 0.2
const AIMROT_Y = 174.4
const AIMROT_Z = 3.1

if arm_anim.is_playing() == false:
		if Input.is_action_pressed("aim") and is_aiming == false:
			is_aiming = true
			var aim_position = Vector3(AIM_X,AIM_Y,AIM_Z)
			var aim_rotation = Vector3(AIMROT_X,AIMROT_Y,AIMROT_Z)
			var pos_tween = create_tween()
			var rot_tween = create_tween()
			pos_tween.tween_property(arm,"position",aim_position,0.2)
			rot_tween.tween_property(arm,"rotation",aim_rotation,0.2)
		elif !Input.is_action_pressed("aim") and is_aiming == true:
			is_aiming = false
			var gun_position = Vector3(GUN_X,GUN_Y,GUN_Z)
			var gun_rotation = Vector3(GUNROT_X,GUNROT_Y,GUNROT_Z)
			var pos_tween = create_tween()
			var rot_tween = create_tween()
			pos_tween.tween_property(arm,"position",gun_position,0.2)
			rot_tween.tween_property(arm,"rotation",gun_rotation,0.2)

And here is a video of what happens:

Any help is greatly appreciated!
`

  • I believe rotation is set in radians, even though the editor shows them in degrees. Your values might be too large.
  • Changing the rotation like that is not a good idea, because there are multiple ways to get from rotation XYZ to another rotation XYZ. The order is undefined, it’s weird. This is precisely what Quaternions are for, maybe look into that. Or rotate the objects with rotate_y() methods and such, that way Godot knows which axes to rotate. I’d rather use Quaternions though. Rotation is hard.

Edit: tweening the rotation directly will result in a correct rotation in the end (provided you use the correct units), but the way Godot rotates the mesh to get there might look weird, or might not be what you’d expect. That is the part where Quaternions come in :slight_smile:

1 Like

Thank you, do you have a good resource on quaternions?

There are a couple of links in the docs you can check out.

However, be aware that Quaternions are very hard to fully understand, because this is a mathematical concept based in 4 dimensions, which is very unintuitive for humans to understand as we can experience only 3 dimensions. I watched already dozens of videos about Quaternions and I still don’t quite get how it works.

So don’t try to understand it fully, because you will most likely fail and get discouraged. What you need to know is that Godot exposes a couple of methods that you can use to rotate Quaternions - you can find them in the linked docs. Play around with these.

1 Like

So if I was to use the constructor,

 Quaternion(arc_from: Vector3, arc_to: Vector3)

and make it

var quat =  Quaternion(gun_rotation, aim_rotation)

How would I then use that quaternion variable to make the arm rotate?

You can tween Quaternions, just as any other parameter. Node3D exposes a quaternion property that you can tween to your desired value.

I changed the code to this

if arm_anim.is_playing() == false:
		if Input.is_action_pressed("aim") and is_aiming == false:
			is_aiming = true
			var aim_position = Vector3(AIM_X,AIM_Y,AIM_Z)
			var aim_rotation = Vector3(AIMROT_X,AIMROT_Y,AIMROT_Z)
			var aim_quat = Quaternion.from_euler(aim_rotation)
			var pos_tween = create_tween()
			var rot_tween = create_tween()
			pos_tween.tween_property(arm,"position",aim_position,0.2)
			rot_tween.tween_property(arm,"quaternion",aim_quat,0.2)
		elif !Input.is_action_pressed("aim") and is_aiming == true:
			is_aiming = false
			var gun_position = Vector3(GUN_X,GUN_Y,GUN_Z)
			var gun_rotation = Vector3(GUNROT_X,GUNROT_Y,GUNROT_Z)
			var gun_quat = Quaternion.from_euler(gun_rotation)
			var pos_tween = create_tween()
			var rot_tween = create_tween()
			pos_tween.tween_property(arm,"position",gun_position,0.2)
			rot_tween.tween_property(arm,"quaternion",gun_quat,0.2)

And now the gun is doing this,

Any idea what I’m doing wrong?

Might be that your final values are just incorrect

Also make sure you are rotating around a point you actually want ! Here I see you are rotating your arm node. Double check if its origin is where you expect it to be. I ofen have dedicated pivot nodes and I offset their mesh children so that it makes sense in the end.

If you can get the rotation you want by tinkering in the editor, you are probably on the right track :slight_smile:

Also a debugging tip: try to make the tween really long, like 10s or more and observe what precisely is happening. Could help.

Good luck

1 Like