0 votes

I have a 3rd person controller which rotates to face the mouse position. It works great except when the player is moved and the mouse stays still. The body faces the last position of the mouse because it only updates on input, so when I move the mouse the player jumps to face it.

I would very much like to get the mouse position on every frame in the physicsprocess(), but it doesn't seem possible. Is there a workaround for this?

extends KinematicBody

var velocity = Vector3 (0,0,0)
const SPEED = 30
onready var base = get_node("..")
var from = Vector3()
var to = Vector3()
onready var camera = get_node("../Camera")
var gravity = 7
export var jumpForce = 75
onready var jumpRay = get_node("JumpRay")

func _input(event):
    if event is InputEventMouseMotion:
        from = camera.project_ray_origin(event.get_position())
        to = from + camera.project_ray_normal(event.get_position()) * 1000

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 = SPEED
    elif Input.is_action_pressed("STRAFE_LEFT"):
        velocity.x = -SPEED
    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 = -SPEED
    elif Input.is_action_pressed("BACK"):
        velocity.z = SPEED
    else:
        velocity.z = lerp(velocity.z,0,0.1)
    move_and_slide(velocity*delta*SPEED)
    if Input.is_action_just_pressed("JUMP") and jumpRay.is_colliding() == true:
        velocity.y = lerp(velocity.y, 1 * jumpForce, 1)
        print("Airborne")
    else: 
        velocity.y = velocity.y - gravity * delta * SPEED
#       velocity.y = velocity.y - gravity
        velocity.y = lerp(velocity.y,0,0.1)
    move_and_slide(velocity*delta*SPEED)

    var cameraOffset = get_translation() + Vector3(11,28,27)
    camera.look_at_from_position(cameraOffset,self.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))
    rayPOS.y = self.get_global_transform().origin.y
    if rayPOS.y != 0: #prevents look_at() alignment error 
        self.look_at(rayPOS,Vector3(0,1,0))
        $guns.look_at(Vector3(rayPOS.x,0,rayPOS.z), Vector3(0,1,0))
in Engine by (36 points)

It would help if you shared your project files, but I guess you could just make your from/to updates into a function that is also called when you walk around.

Unless I'm mistaken mouse position can't be called outside of _input().

1 Answer

0 votes

Save the last known mouse position (event.get_position()) in a variable and calculate/update "from" and "to" in the _physics_process function instead of the input function.

by (1,694 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 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 webmaster@godotengine.org with your username.