Is it possible to control rate of 3D rotation with a tween?

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By DKesserich
:warning: Old Version Published before Godot 3 was released.

My use case is giving movement commands in a Homeworld-esque 3D RTS.

I want my selected unit to rotate to face the location of the movement command in 3D space and then go to that location.

transform = transform.looking_at(targetLocation, Vector3(0,1,0)) will instantly snap the objects rotation to the correct place, which isn’t exactly what I want.

I’m looking at trying it with a tween, but since interpolate_property() takes time as an argument that means it would take the same amount of time for the object to rotate 45 degrees as it would to rotate 180 degrees.

Is there a good way to control the rotation speed with tween? Or even a lerp or slerp? I tried a really hacky lerp call (because I didn’t know about Quat slerp) already and it’s exhibiting some bizarre behaviour and still has the same “takes the same amount of time regardless of how far it rotates” problem.

Is dividing the dot product by the rotation speed and using that as the time argument a possibility (I think this would work in 2D, but I’m missing something in 3D because it may have to rotate on all of its axes. The “Pointing at Target” bit in the Vector Math tutorial seems lacking in detail)?

What do you mean by “controlling speed”? Do you mean you just want your tween to have a non-linear speed? You could use easing curves for that.

Zylann | 2018-01-05 13:59

What do you mean by “controlling speed”? Do you mean you just want your tween to have a non-linear speed? You could use easing curves for that.

No, I mean I want it to turn at no more than 90 degrees/sec (or 120, or 15, or whatever) when it could be turning anywhere from 1 to 180 degrees.

DKesserich | 2018-01-05 19:56

:bust_in_silhouette: Reply From: DKesserich

So I was overcomplicating it and the answer is “yes” Code below does it:

var rotSpeed = 90 #rotation speed in degrees per second
var angleDiff = acos(transform.basis.z.dot(
transform.looking_at(targetLocation,
Vector3(0,1,0)).basis.z

var timeToTurn = angleDiff/deg2rad(rotSpeed)

tween.interpolate_property(self,"rotation_degrees",
		rotation_degrees,
		Vector3(rad2deg(facingAngle.x),
            rad2deg(facingAngle.y),
            rad2deg(facingAngle.z)),
		timeToTurn,
        trans_type,
        ease_type)
tween.start()