Is there a GDScript function to lerp between two angles?
For example, make it so 270° => 20° doesn't go backwards.

in Engine
edited

One possible solution is to convert angle to float and lerp with the float, then convert to back to angle and use it.

by (683 points)

What do you mean by angle? My angle is already a float variable.

Take normalized directional vectors for angles.
A vector 1,0 will be 0 deg, vector 0,1 will be 90deg.

Then lerp between these vectors and find the angle of the resulting vector.

There are easier solutions for this if you manually calculate the angle instead of lerping. Or if you want to lerp the rotation of something, there is quaternion slerp in gdscript.

by (750 points)

I actually compute the angle myself, and it's 2D so I don't use quaternions. Converting back and forth in vectors could work but I'm sure there is a faster way.

I found a solution:

static func lerp_angle(a, b, t):
if abs(a-b) >= PI:
if a > b:
a = normalize_angle(a) - 2.0 * PI
else:
b = normalize_angle(b) - 2.0 * PI
return lerp(a, b, t)

static func normalize_angle(x):
return fposmod(x + PI, 2.0*PI) - PI

An example project:
http://zylannprods.fr/dl/godot/LerpAngle.zip

by (28,789 points)

Thank you! I've been trying to figure this out for a while.

EDIT: Godot now has a lerp_angle function.

Zylann's solution doesn't seem to work when there's an offset before the lerping:

func _process(delta):
var to_mouse = \$Sprite.global_position - get_global_mouse_position()
var offset = -PI / 2
var rotation_to_mouse = to_mouse.angle() + offset
\$Sprite.rotation = lerp_angle(\$Sprite.rotation, rotation_to_mouse, 0.25)

So this is an alternative which works in that case

func lerp_angle(from, to, weight):
return from + short_angle_dist(from, to) * weight

func short_angle_dist(from, to):
var max_angle = PI * 2
var difference = fmod(to - from, max_angle)
return fmod(2 * difference, max_angle) - difference
by (4,163 points)
edited

thanks, man. it works!

You can use wrapf, wrap the difference in -PI to PI

func lerp_angle(from, to, weight):
var diff = wrapf(to - from, -PI, PI)
var i = lerp(from, from + diff, weight)
# Keep the result in 0..2*PI
i = wrapf(i, 0, 2*PI)
return i