+1 vote

Hey. I am moving and rotating my Player with the following lines:

func physics_process(delta):
    player.motion = player.position.direction_to(player.get_global_mouse_position()) * 600


The look_at method makes it turn almost instantly. I want to make that more smooth. Can anyone help me with this please? (Maybe with a Tween?)


Edit: If you're wondering why I am using a reference to the player and why I don't use physicsprocess(delta). This script is from a subclass of a State machine which controls Player movement. The actual physicsprocess method is in the Base Class.

in Engine by (30 points)

4 Answers

0 votes

I am currently looking for the same thing.

After searching the web this code was pointed to me as a possible solution, but I am not very familiar with tweens. This code is also really fast and I can't seem to make it turn slower.

Hope it helps anyway.

extends Node2D

onready var TweenNode = get_node("Tween")

func _process(delta):

# target to look at
var target = get_global_mouse_position()

# initial and final x-vector of basis
var initial_transform_x = self.transform.x
var final_transform_x = (target - self.global_position).normalized()

# interpolate
TweenNode.interpolate_method(self, '_set_rotation', initial_transform_x, final_transform_x, 0.1, Tween.TRANS_LINEAR, Tween.EASE_OUT)

apply rotation

func setrotation(new_transform):

# apply tweened x-vector of basis
self.transform.x = new_transform

# make x and y orthogonal and normalized
self.transform = self.transform.orthonormalized()
by (30 points)
+3 votes

lookat is not the function you need, you need lookingat, which creates a new transform.
i basically create a new transform that look at the target, and then i used lerp to interpolate the x,y,z basis of the camera transform with the one of the created transform

func _process(delta):  #inside camera process
        var T=global_transform.looking_at(target.global_transform.origin, Vector3(0,1,0))
        global_transform.basis.y=lerp(global_transform.basis.y, T.basis.y, delta*camera_speed)
        global_transform.basis.x=lerp(global_transform.basis.x, T.basis.x, delta*camera_speed)
        global_transform.basis.z=lerp(global_transform.basis.z, T.basis.z, delta*camera_speed)
by (1,514 points)

I previously commented that this works perfectly but actually it doesn't. It works in one direction but it scales the model in a negative direction sometimes. Especially if it is a 180 degree turn.

You are right, above solution does not work with 180° turn.
Rotation happens when at least 1 basis vector changes direction (the others follow automatically using an orthonormalization process), but in case of a 180° turn, you are just changing the magnitude of one of the vectors and keep the other 2 as the same. Therefore the lerping just shrink the part and then it flips it.

I suggest to add a line of "if" code to intercept those situation, and rotate the part toward a 90° direction first, before continuing toward the 180° one

+6 votes

This solution definitely isn't the best, but it's very simple and easy to grasp, so this is how I do it:

var weight = 0.1

func physics_process(delta):
    player.motion = player.position.direction_to(player.get_global_mouse_position()) * 600

    player.rotation = lerp_angle(player.rotation, (player.get_global_mouse_position() - player.global_position).normalized().angle(), weight)
by (112 points)
0 votes

This is the right solution:


(sample code https://godotengine.org/asset-library/asset/674)

I tried it and works perfectly.

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