Smooth Rotation

Godot Version

4.6

Question

Hello! I’m currently working on a game with tank enemies, and I want a tank to have a searching state where it’s turret rotates around and looks in different directions. I’ve written some code that technically accomplishes this, however the turret just snaps to certain directions and I want it to smoothly rotate towards them. In the future I plan to have the turret stop for a moment, but for now I just want to see the turret smoothly look from one direction to another. Any help would be greatly appreciated!

Code that controls tank functionality

func _physics_process(_delta):
	if is_looking == false:
		look()
	
		
func look():
	is_looking = true
	sprite = actor.turret
	
	rotate_diretion = randf_range(-1, 1)
	rotate_time = randf_range(1, 3)
	
	sprite.rotate(rotate_diretion)
	
	await get_tree().create_timer(rotate_time).timeout
	is_looking = false
1 Like

Typically you should a Timer node instead of creating timers on the scene tree continually. You can use $Timer.start(rotate_time) to use the random time.

To rotate over time use a target_angle variable to rotate towards. Then your _process function can move towards it.

You may need a move_toward that functions better with angles, I use this function in a few of my projects

func move_toward_angle(value: float, target: float, delta: float) -> float:
	var diff := fmod(target - value, TAU)
	var dir := signf(diff)
	if absf(diff) > PI:
		dir = -dir # angle probably closer in opposite direction

	if absf(diff) > delta:
		return value + dir * delta
	else:
		return target

It is used similar to move_toward

func _process(delta: float) -> void:
    rotation = move_toward_angle(rotation, target_rotation, rotation_speed * delta)

Sorry for the late response, but could you please walk through and explain what your code does? I somewhat understand it, but I don’t quite get the thought process behind it.

Instead of setting the rotation outright with sprite.rotate(new_direction), apply it over time through _process.

If you wanted your turret to spin forever you could add to it’s rotation, a negative speed would spin backwards.

rotation += rotation_speed * delta

If you have a target value you want to slowly encroach but not go over, the built in method move_toward is great for that

rotation = move_toward(rotation, target_roation, rotation_speed * delta)

But this function doesn’t handle angles properly, it doesn’t know that rotations wrap around at TAU or negative numbers. The move_toward_angle function I posted does and chooses the fastest path to reach the target rotation.


As a nitpick you should avoid get_tree().create_timer, Timer is almost always a better fit, or other signals.

Alright, I got it! Thanks for the help :grinning_face_with_smiling_eyes:

lerping is really what you want to do…

Interpolation — Godot Engine (stable) documentation in English