Hello,
I'm using this code:

to create a smooth turn whenever I move, but for some reason it keeps defaulting back to due north when I stop pressing any keys. If possible, I would like it to face the direction it stopped at.

  • I got it working. This is what I used:

    extends KinematicBody
    
    var velocity = Vector3.ZERO
    var last_velocity = Vector3.ZERO
    var direction = Vector3.ZERO
    export (int) var fall_acceleration = 75
    export (int) var speed = 5
    export(int) var rotSpeed = 1
    export (int) var angluar_acceleration = 10
    var character_rot
    
    func _physics_process(delta):
    	direction = Vector3.ZERO
    	character_rot = $model.get_rotation()
    	if Input.is_action_pressed("MoveBackward"):
    		direction.z = 1
    	if Input.is_action_pressed("MoveForward"):
    		direction.z -= 1
    	if Input.is_action_pressed("MoveLeft"):
    		direction.x = -1
    	if Input.is_action_pressed("MoveRight"):
    		direction.x += 1
    	if Input.is_action_pressed("MoveBackward") || Input.is_action_pressed("MoveForward") || Input.is_action_pressed("MoveLeft") || Input.is_action_pressed("MoveRight"):
    		velocity = Vector3(Input.get_action_strength("MoveLeft") - Input.get_action_strength("MoveRight"),
    		0,
    		Input.get_action_strength("MoveForward") - Input.get_action_strength("MoveBackward")).normalized()
    	else:
    		rotSpeed = 0
    	
    	if velocity.length_squared() > 0.1:
    		var angle = atan2(-velocity.x, -velocity.z)
    		character_rot.y = lerp_angle(character_rot.y, angle, .1)
    		$model.set_rotation(character_rot)
    	
    	
    	velocity.x = direction.x * speed
    	velocity.z = direction.z * speed
    	velocity.y -= fall_acceleration * delta
    	velocity = move_and_slide(velocity * speed, Vector3.UP)

It would be better if you posted the code text on the forum, not screenshots. Screenshots are hard to read, and can't be searched, or copied pasted. You can post code by typing 3 tildes ~~~ on a line by themselves directly above and directly below the code text.

To answer you question, you are setting direction equal to zero on the first line of process, so if no keys are pressed, you will have (0, 0, 0) for the rotation. You likely want to move the "var direction ..." line to the top under velocity and then change the inputs to use absolute instead of relative when adding 1. I would edit the code for you, but I can't, since you posted images rather than text.

    cybereality

    cybereality Sorry about the screenshots, and thanks for the help. I’ll try it. The weird part is the character doesn’t start facing (0, 0, 0), it starts facing (0, 180, 0). Or maybe I’m mistaken, I’ll still try it and let you know.

    cybereality I moved the var line, and for some reason it caused the character to fly around the screen. I'm also not sure what you mean by absolutes. Here's the code, sorry about the screenshots

    extends KinematicBody
    
    var velocity = Vector3.ZERO
    export (int) var fall_acceleration = 75
    export (int) var speed = 5
    export(int) var rotSpeed = 1
    export (int) var angluar_acceleration = 10
    
    func _physics_process(delta):
    	var direction = Vector3.ZERO
    	if Input.is_action_pressed("MoveBackward"):
    		direction.z += 1
    	if Input.is_action_pressed("MoveForward"):
    		direction.z -= 1
    	if Input.is_action_pressed("MoveLeft"):
    		direction.x -= 1
    	if Input.is_action_pressed("MoveRight"):
    		direction.x += 1
    	if Input.is_action_pressed("MoveBackward") || Input.is_action_pressed("MoveForward") || Input.is_action_pressed("MoveLeft") || Input.is_action_pressed("MoveRight"):
    		velocity = Vector3(Input.get_action_strength("MoveLeft") - Input.get_action_strength("MoveRight"),
    		0,
    		Input.get_action_strength("MoveForward") - Input.get_action_strength("MoveBackward")).normalized()
    	else:
    		rotSpeed = 0
    	
    	$model.rotation.y = lerp_angle($model.rotation.y, atan2(-velocity.x, -velocity.z), delta * angluar_acceleration)
    	
    	#self.move_and_slide(velocity * speed, Vector3.UP)
    	velocity.x = direction.x * speed
    	velocity.z = direction.z * speed
    	velocity.y -= fall_acceleration * delta
    	velocity = move_and_slide(velocity * speed, Vector3.UP)

    I meant like this:

    var velocity = Vector3.ZERO
    var direction = Vector3.ZERO
    export (int) var fall_acceleration = 75
    export (int) var speed = 5
    export(int) var rotSpeed = 1
    export (int) var angluar_acceleration = 10
    
    func _physics_process(delta):
    	if Input.is_action_pressed("MoveBackward"):
    		direction.z = 1
    	if Input.is_action_pressed("MoveForward"):
    		direction.z -= 1
    	if Input.is_action_pressed("MoveLeft"):
    		direction.x = -1
    	if Input.is_action_pressed("MoveRight"):
    		direction.x += 1
    	if Input.is_action_pressed("MoveBackward") || Input.is_action_pressed("MoveForward") || Input.is_action_pressed("MoveLeft") || Input.is_action_pressed("MoveRight"):
    		velocity = Vector3(Input.get_action_strength("MoveLeft") - Input.get_action_strength("MoveRight"),
    		0,
    		Input.get_action_strength("MoveForward") - Input.get_action_strength("MoveBackward")).normalized()
    	else:
    		rotSpeed = 0
    	
    	$model.rotation.y = lerp_angle($model.rotation.y, atan2(-velocity.x, -velocity.z), delta * angluar_acceleration)
    	
    	#self.move_and_slide(velocity * speed, Vector3.UP)
    	velocity.x = direction.x * speed
    	velocity.z = direction.z * speed
    	velocity.y -= fall_acceleration * delta
    	velocity = move_and_slide(velocity * speed, Vector3.UP)

      cybereality That didn't work, all it did was make him go flying whenever I hit a key lol. The only change I see is the movement of the var, where is the absolutes change?

      Sorry, try this:

      var velocity = Vector3.ZERO
      var last_velocity = Vector3.ZERO
      var direction = Vector3.ZERO
      export (int) var fall_acceleration = 75
      export (int) var speed = 5
      export(int) var rotSpeed = 1
      export (int) var angluar_acceleration = 10
      
      func _physics_process(delta):
      	direction = Vector3.ZERO
      	if Input.is_action_pressed("MoveBackward"):
      		direction.z = 1
      	if Input.is_action_pressed("MoveForward"):
      		direction.z -= 1
      	if Input.is_action_pressed("MoveLeft"):
      		direction.x = -1
      	if Input.is_action_pressed("MoveRight"):
      		direction.x += 1
      	if Input.is_action_pressed("MoveBackward") || Input.is_action_pressed("MoveForward") || Input.is_action_pressed("MoveLeft") || Input.is_action_pressed("MoveRight"):
      		velocity = Vector3(Input.get_action_strength("MoveLeft") - Input.get_action_strength("MoveRight"),
      		0,
      		Input.get_action_strength("MoveForward") - Input.get_action_strength("MoveBackward")).normalized()
      	else:
      		rotSpeed = 0
      	
      	if velocity.length_squared() > 0.1:
      		last_velocity = velocity
      	$model.rotation.y = lerp_angle($model.rotation.y, atan2(-last_velocity.x, -last_velocity.z), delta * angluar_acceleration)
      	
      	velocity.x = direction.x * speed
      	velocity.z = direction.z * speed
      	velocity.y -= fall_acceleration * delta
      	velocity = move_and_slide(velocity * speed, Vector3.UP)

        cybereality I tried it, and it works almost perfectly, but when the character stops they don't stop facing the direction they were last moving in. Instead, the turn 180 degrees and face the other way.

        Then it has something to do with these lines.

        if velocity.length_squared() > 0.1:
        	last_velocity = velocity
        $model.rotation.y = lerp_angle($model.rotation.y, atan2(-last_velocity.x, -last_velocity.z), delta * angluar_acceleration)

        Honestly, that atan2 call doesn't make sense to me. Why are you using the negative value? Also, atan2 typically works with the reversed axis. In 2D it would be atan2(velocity.y, velocity.x). So the logic here seems incorrect.

          cybereality I'm not sure, honestly I wasn't sure how to accomplish the task of turning the character such as I need since I've never worked with 3d before. I tried changing the negatives to positives, but no dice. If you have a suggestion that isn't atan2 I would love to hear it, but if not I could search for something else. You've already been a major help and I'd hate to bother you further.

          I got it working. This is what I used:

          extends KinematicBody
          
          var velocity = Vector3.ZERO
          var last_velocity = Vector3.ZERO
          var direction = Vector3.ZERO
          export (int) var fall_acceleration = 75
          export (int) var speed = 5
          export(int) var rotSpeed = 1
          export (int) var angluar_acceleration = 10
          var character_rot
          
          func _physics_process(delta):
          	direction = Vector3.ZERO
          	character_rot = $model.get_rotation()
          	if Input.is_action_pressed("MoveBackward"):
          		direction.z = 1
          	if Input.is_action_pressed("MoveForward"):
          		direction.z -= 1
          	if Input.is_action_pressed("MoveLeft"):
          		direction.x = -1
          	if Input.is_action_pressed("MoveRight"):
          		direction.x += 1
          	if Input.is_action_pressed("MoveBackward") || Input.is_action_pressed("MoveForward") || Input.is_action_pressed("MoveLeft") || Input.is_action_pressed("MoveRight"):
          		velocity = Vector3(Input.get_action_strength("MoveLeft") - Input.get_action_strength("MoveRight"),
          		0,
          		Input.get_action_strength("MoveForward") - Input.get_action_strength("MoveBackward")).normalized()
          	else:
          		rotSpeed = 0
          	
          	if velocity.length_squared() > 0.1:
          		var angle = atan2(-velocity.x, -velocity.z)
          		character_rot.y = lerp_angle(character_rot.y, angle, .1)
          		$model.set_rotation(character_rot)
          	
          	
          	velocity.x = direction.x * speed
          	velocity.z = direction.z * speed
          	velocity.y -= fall_acceleration * delta
          	velocity = move_and_slide(velocity * speed, Vector3.UP)