In my game I have a turret, which I want it to be constantly aiming to the player, and the rotation needs to be at a constant speed (slow)

I tried this:

``````var rotation_speed = 0.1

func _process(delta):
var player_dir = get_parent().get_node("Player").global_position - global_position

rotation = lerp_angle(rotation,player_dir.angle(),rotation_speed)
``````

But it makes the turret to rotate faster when it's trying to aim to the player and to slow down as it gets closer

Is there any way to fix that?

Godot version Godot 3.2.2
in Engine

Have you tried using `look_at()`? Is your game 2D or 3D?

Yeah, I tried that, but I need a delayed rotation

Edit: is a 2D game

+1 vote

To go toward a value at a constant speed, you generally divide the difference by its length, and then multiply it by the speed:
`var difference := player_dir.angle() - rotation`
`if difference != 0:`
`. rotation = rotation + (difference / abs(difference) * speed)`

by (2,484 points)
selected by

Dividing by the length is how you normalize a vector, but this is an angle, so dividing by the length just gives you one.

Well, I added my solution but after some tests I saw that yours also works, even with less lines of code
The only problem I had with your solution is that I had to `speed * delta`
Thank you!!!

Ok I figured it out

I had to use the difference of the angles (as Lopy said) and the dot product

I'll put the code here in case anyone needs it:

``````var rotation_speed = deg2rad(45.0) # Since all values are in radians, this needs to be in radians too

func getDot(vector1: Vector2, _vector2:Vector2) -> float:
var n1 = vector1.normalized()
var n2 = _vector2.normalized()

var vDot = n1.dot(n2.tangent()) # Why the tangent? Because the dot product is 0.0 when the angle between 2 vectors is 90º, and I need it to give 0.0 when the angle is 0º

return vDot

func _process(delta):
var player_dir = get_parent().get_node("Player").global_position - global_position
var angle = polar2cartesian(1.0,rotation) # This var is to obtain a vector with the turret angle so I can obtain a dot product
var difference : float = player_dir.angle() - angle.angle()
dot = getDot(angle, player_dir)

if difference != 0:
if abs(difference) > 0.1:
\$icon.rotation += sign(dot) * rotation_speed * delta # If the dot product is < 0 that would make the turret to rotate counter-clockwise and the other way around
``````

Maybe this can be optimized, but it works
Thanks for the help!

by (19 points)
edited by