The game is third person with a camera that follows the player. The player can rotates to follow the mouse motion. I'm using lookat() for rotation and moveand_slide() for movement. The problem is that when I rotate the player movement get slower the closer it gets to perpendicular to the forward rotation.

Here's a video:
https://youtu.be/PBpIdQSEyuY

lookat() and moveand_slide() are both global space and I know I could rotate the player locally, but it makes firing projectiles much more complicated.

Here's my controller:
(doing the look_at() in _process() isn't necessary but it seems to run faster that way)

``````var from = Vector3()
var to = Vector3()
export var gravity = .1
export var jumpForce = 30
var velocity = Vector3(0,0,0)
export var SPEED = 30

func _physics_process(delta):
if Input.is_action_pressed("STRAFE_RIGHT") and Input.is_action_pressed("STRAFE_LEFT"):
velocity.x = 0
elif Input.is_action_pressed("STRAFE_RIGHT"):
velocity.x = 1
elif Input.is_action_pressed("STRAFE_LEFT"):
velocity.x = -1
else:
velocity.x = lerp(velocity.x,0,0.1)
if Input.is_action_pressed("FORWARD") and Input.is_action_pressed("BACK"):
velocity.z = 0
elif Input.is_action_pressed("FORWARD"):
velocity.z = -1
elif Input.is_action_pressed("BACK"):
velocity.z = 1
else:
velocity.z = lerp(velocity.z,0,0.1)

if Input.is_action_just_pressed("JUMP") and jumpRay.is_colliding() == true:
velocity.y = lerp(velocity.y, velocity.y * -jumpForce, .1)
else:
velocity.y = velocity.y - gravity
velocity.y = lerp(velocity.y,0,0.1)

move_and_slide(velocity*SPEED)

func _process(delta):
from = camera.project_ray_origin(get_viewport().get_mouse_position())
to = from + camera.project_ray_normal(get_viewport().get_mouse_position()) * 1000

var cameraOffset = get_translation() + Vector3(11,28,27)
camera.look_at_from_position(cameraOffset,get_translation(),Vector3(0,1,0))

var space_state = get_world().direct_space_state
var ray = space_state.intersect_ray(from, to, [self,\$guns,base],1, true, true)
var rayPOS = ray.get("position",Vector3(0,1,0))
\$guns.look_at(Vector3(rayPOS.x,rayPOS.y,rayPOS.z), Vector3(0,1,0))
rayPOS.y = get_global_transform().origin.y
look_at(rayPOS,Vector3(0,1,0))
``````
in Engine

Okay I figured out what I was doing wrong.

I decoupled the rotation from the movement by nesting the player's KinematicBody inside another KinematicBody. So the tree looks like this:

MAIN (move this)
|-BODY (rotate this)

It's also VERY important that the collision bodies of these two are separated. I just put the BODY in a different layer and set the masks appropriately.

Very simple and pretty obvious now that I figured it out. All it took was a good nights sleep.

by (36 points)
edited