0 votes

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 by (19 points)

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

2 Answers

+1 vote
Best answer

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,688 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!!!

0 votes

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
Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read Frequently asked questions and How to use this Q&A? before posting your first questions.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to [email protected] with your username.