You are doing some odd mix of things here.
Unused input_angle
First, of all, just copying the over to Godot. I get a warning that input_angle is not used. And after a quick look, _target_angle right next is never assigned:
var input_angle := turn_input.angle()
var _target_angle:float
That is an easy fix. Just keep _target_angle:
var _target_angle := turn_input.angle()
Clean up
Second, not really a problem, but movement is this:
var movement := Vector3(turn_input.x, 0.0, turn_input.y).normalized()
With that, you see all this code:
if Input.is_action_pressed("move_forward") and Input.is_action_pressed("move_left"):
movement[2] = 1
movement[0] = 1
elif Input.is_action_pressed("move_forward") and Input.is_action_pressed("move_right"):
movement[2] = 1
movement[0] = -1
elif Input.is_action_pressed("move_backward") and Input.is_action_pressed("move_left"):
movement[2] = -1
movement[0] = 1
elif Input.is_action_pressed("move_backward") and Input.is_action_pressed("move_right"):
movement[2] = -1
movement[0] = -1
else:
if Input.is_action_pressed("move_forward"):
movement[2] = 1
if Input.is_action_pressed("move_backward"):
movement[2] = -1
if Input.is_action_pressed("move_left"):
movement[0] = 1
if Input.is_action_pressed("move_right"):
movement[0] = -1
movement = movement.normalized()
Delete it. Gone. Just keep the one liner above. It should do the same thing. It should do the same thing, with the weird behavior and all, but it is easier to see the code now.
The code looks like this now:
extends KinematicBody
var moveSpeed : float = 5.0
var jumpForce : float = 10.0
var gravity : float = 20
var vel : Vector3 = Vector3()
const _angular_speed:float = TAU
func _physics_process(delta):
vel.x = 0
vel.z = 0
var turn_input := Vector2(
Input.get_action_strength("move_left") - Input.get_action_strength("move_right"),
Input.get_action_strength("move_forward") - Input.get_action_strength("move_backward")
)
var _target_angle := turn_input.angle()
var angle_diff := wrapf(_target_angle - rotation.y, -PI, PI)
rotation.y += clamp(delta * _angular_speed, 0, abs(angle_diff)) * sign(angle_diff)
var movement := Vector3(turn_input.x, 0.0, turn_input.y).normalized()
global_transform[3] += movement/7
vel.y -= gravity * delta
if Input.is_action_pressed("jump") and is_on_floor():
vel.y = jumpForce
vel = move_and_slide(vel, Vector3.UP)
What the movement?
Look at this line:
global_transform[3] += movement/7
What the Hell, Michigan?
That line is equivalent to this:
global_transform.origin += movement * 1/7
Notice this is motion, and it is not using delta. I will come back to that.
Rotation resetting
We need to promote _target_angle to a field, and only set it when there is some input. I also did clean the field further. The code now looks like this:
extends KinematicBody
const _angular_speed:float = TAU
var moveSpeed := 5.0
var jumpForce := 10.0
var gravity := 20
var vel := Vector3()
var _target_angle:float
func _physics_process(delta):
vel.x = 0
vel.z = 0
var turn_input := Vector2(
Input.get_action_strength("move_left") - Input.get_action_strength("move_right"),
Input.get_action_strength("move_forward") - Input.get_action_strength("move_backward")
)
if turn_input.length_squared() > 0:
_target_angle = turn_input.angle()
var angle_diff := wrapf(_target_angle - rotation.y, -PI, PI)
rotation.y += clamp(delta * _angular_speed, 0, abs(angle_diff)) * sign(angle_diff)
var movement := Vector3(turn_input.x, 0.0, turn_input.y).normalized()
global_transform[3] += movement/7
vel.y -= gravity * delta
if Input.is_action_pressed("jump") and is_on_floor():
vel.y = jumpForce
vel = move_and_slide(vel, Vector3.UP)
As you can see I declare target_angle at the start, so it is not a local variable. That way, it keeps its value. Also I do this:
if turn_input.length_squared() > 0:
_target_angle = turn_input.angle()
That way, only when turn_input is not empty, it sets _target_angle.
Wrong direction
It seems to be moving in the opposite direction it should. I'm not sure if this is intentional or not, given that I kept the order you had.
Anyway, fixing it is a matter of flipping the input:
var turn_input := Vector2(
Input.get_action_strength("move_right") - Input.get_action_strength("move_left"),
Input.get_action_strength("move_backward") - Input.get_action_strength("move_forward")
)
This makes sense given that x grows to the right, and - actually - forward in Godot is negative z (here stored in the y).
Wrong orientation
The rotation of the character seems to be off by a quarter turn. This solves it:
_target_angle = 0.75 * TAU - turn_input.angle()
Actually it makes sense given that turn_input.angle() would be measured from the x axis, but 0 rotation is looking down the z axis. I did overlook that.
Motion again
Instead of changing the origin of the transform (by snaky means, no less), use move_and_slide, which you are already using. Thus, we are not going to have movement, instead we are going to write to vel. To ease doing that, I decided to normalize turn_input so we can use it directly to compute vel. And while we are at it, let us use the moveSpeed field you have. Which is very small by the way.
This is the final code:
extends KinematicBody
const _angular_speed:float = TAU
var moveSpeed := 500.0
var jumpForce := 10.0
var gravity := 20
var vel := Vector3()
var _target_angle:float
func _physics_process(delta:float) -> void:
# Input
var turn_input := Vector2(
Input.get_action_strength("move_right") - Input.get_action_strength("move_left"),
Input.get_action_strength("move_backward") - Input.get_action_strength("move_forward")
).normalized()
# Rotation
if turn_input.length_squared() > 0:
_target_angle = 0.75 * TAU - turn_input.angle()
var angle_diff := wrapf(_target_angle - rotation.y, -PI, PI)
rotation.y += clamp(delta * _angular_speed, 0, abs(angle_diff)) * sign(angle_diff)
# Velocity
vel.x = turn_input.x * moveSpeed * delta
vel.z = turn_input.y * moveSpeed * delta
vel.y -= gravity * delta
if Input.is_action_pressed("jump") and is_on_floor():
vel.y = jumpForce
# Motion
vel = move_and_slide(vel, Vector3.UP)