0 votes

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()
onready var camera = get_node("../Camera")
onready var jumpRay = get_node("JumpRay")
onready var base = get_node("..")
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))
asked Sep 7, 2019 in Engine by spiderbyte87 (33 points)

1 Answer

0 votes

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.

answered Sep 8, 2019 by spiderbyte87 (33 points)
edited Sep 8, 2019 by spiderbyte87
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 How to use this Q&A? before posting your first questions.