After following these tutorials (first person controller series by https://www.youtube.com/@lukky.
) and making a first person controller in godot4.
Every time I finish sliding, my camera snaps back to the front. But how can I avoid that and instead keep the position? Better explanation: I don't like it how after you slide, you snap back to your front. I want to just continue looking at was I was looking, so I don't have to move my mouse again, and can instantly go.
My code:
extends CharacterBody3D
# Player nodes
@onready var neck = $Neck
@onready var head = $Neck/Head
@onready var eyes = $Neck/Head/Eyes
@onready var standing_collision_shape = $StandingCollisionShape
@onready var crouching_collisiong_shape = $CrouchingCollisiongShape
@onready var up_ray_cast = $UpRayCast
@onready var camera_3d = $Neck/Head/Eyes/Camera3D
@onready var animation_player = $Neck/Head/Eyes/AnimationPlayer
# Speed vars
var current_speed = 5.0
const walking_speed = 5.0
const sprinting_speed = 8.0
const crouching_speed = 3.0
# States
var walking = false
var sprinting = false
var crouching = false
var free_looking = false
var sliding = false
# Slide vars
var slide_timer = 0.0
var slide_timer_max = 1.0
var slide_vector = Vector2.ZERO
var slide_speed = 13.0
# Head bobbing vars
const head_bobbing_sprinting_speed = 22.0
const head_bobbing_walking_speed = 14.0
const head_bobbing_crouching_speed = 10.0
const head_bobbing_sprinting_intensity = 0.2
const head_bobbing_walking_intensity = 0.1
const head_bobbing_crouching_intensity = 0.05
var head_bobbing_vector = Vector2.ZERO
var head_bobbing_index = 0.0
var head_bobbing_current_intensity = 0.0
# Movement vars
const jump_velocity = 5.5
var crouching_depth = -0.5
var lerp_speed = 10.0
var air_lerp_speed = 3.0
var free_look_tilt_amount = 8
var last_velocity = Vector3.ZERO
# Input vars
var direction = Vector3.ZERO
const mouse_sens = 0.1
# Get the gravity from the project settings to be synced with RigidBody nodes.
var gravity = ProjectSettings.get_setting("physics/3d/default_gravity")
func _ready():
Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
func _input(event):
# Mouse looking logic
if event is InputEventMouseMotion:
if free_looking:
neck.rotate_y(deg_to_rad(-event.relative.x * mouse_sens))
neck.rotation.y = clamp(neck.rotation.y, deg_to_rad(-120), deg_to_rad(120))
else:
rotate_y(deg_to_rad(-event.relative.x * mouse_sens))
head.rotate_x(deg_to_rad(-event.relative.y * mouse_sens))
head.rotation.x = clamp(head.rotation.x, deg_to_rad(-89), deg_to_rad(89))
func _physics_process(delta):
# Getting movement input
var input_dir = Input.get_vector("left", "right", "forward", "backward")
# Handle movement state
# Crouching
if Input.is_action_pressed("crouch") || sliding:
current_speed = lerp(current_speed, crouching_speed, delta * lerp_speed)
head.position.y = lerp(head.position.y, crouching_depth, delta * lerp_speed)
crouching_collisiong_shape.disabled = false
standing_collision_shape.disabled = true
# Slide begin logic
if sprinting && input_dir != Vector2.ZERO:
sliding = true
slide_timer = slide_timer_max
slide_vector = input_dir
free_looking = true
walking = false
sprinting = false
crouching = true
elif not up_ray_cast.is_colliding():
# Standing
standing_collision_shape.disabled = false
crouching_collisiong_shape.disabled = true
head.position.y = lerp(head.position.y, 0.0, delta * lerp_speed)
if Input.is_action_pressed("sprint"):
# Sprinting
current_speed = lerp(current_speed, sprinting_speed, delta * lerp_speed)
walking = false
sprinting = true
crouching = false
else:
# Walking
current_speed = lerp(current_speed, walking_speed, delta * lerp_speed)
walking = true
sprinting = false
crouching = false
# Handle free looking
if Input.is_action_pressed("free_look") || sliding:
free_looking = true
if sliding:
eyes.rotation.z = lerp(eyes.rotation.z, -deg_to_rad(7.0), delta * lerp_speed)
else:
eyes.rotation.z = -deg_to_rad(neck.rotation.y * free_look_tilt_amount)
else:
free_looking = false
neck.rotation.y = lerp(neck.rotation.y, 0.0, delta * lerp_speed)
eyes.rotation.z = lerp(eyes.rotation.z, 0.0, delta * lerp_speed)
# Hanle sliding
if sliding:
slide_timer -= delta
if slide_timer <= 0:
sliding = false
free_looking = false
# Handle headbob
if sprinting:
head_bobbing_current_intensity = head_bobbing_sprinting_intensity
head_bobbing_index += head_bobbing_sprinting_speed * delta
elif walking:
head_bobbing_current_intensity = head_bobbing_walking_intensity
head_bobbing_index += head_bobbing_walking_speed * delta
elif crouching:
head_bobbing_current_intensity = head_bobbing_crouching_intensity
head_bobbing_index += head_bobbing_crouching_speed * delta
if is_on_floor() && !sliding && input_dir != Vector2.ZERO:
head_bobbing_vector.y = sin(head_bobbing_index)
head_bobbing_vector.x = sin(head_bobbing_index / 2) + 0.5
eyes.position.y = lerp(eyes.position.y, head_bobbing_vector.y * (head_bobbing_current_intensity / 2.0), delta * lerp_speed) # can tweak 2.0
eyes.position.x = lerp(eyes.position.x, head_bobbing_vector.x * head_bobbing_current_intensity, delta * lerp_speed)
else:
eyes.position.y = lerp(eyes.position.y, 0.0, delta * lerp_speed)
eyes.position.x = lerp(eyes.position.x, 0.0, delta * lerp_speed)
# ------------MOVEMENT CODE------------ #
# Add the gravity.
if not is_on_floor():
velocity.y -= gravity * delta
# Handle Jump.
if Input.is_action_just_pressed("jump") and is_on_floor():
velocity.y = jump_velocity
sliding = false # MAYBE LATER MAKE "C" SLIDE CANCEL INSTEAD OF SPACE (But still keep slide jumping)
animation_player.play("jump")
# Handle landing
if is_on_floor():
if last_velocity.y < -10.0:
animation_player.play("roll")
elif last_velocity.y < -4.0:
animation_player.play("landing")
# Get the input direction and handle the movement/deceleration.
# As good practice, you should replace UI actions with custom gameplay actions.
if is_on_floor():
direction = lerp(direction, transform.basis * Vector3(input_dir.x, 0, input_dir.y).normalized(), delta * lerp_speed)
else:
if input_dir != Vector2.ZERO:
direction = lerp(direction, transform.basis * Vector3(input_dir.x, 0, input_dir.y).normalized(), delta * air_lerp_speed)
if sliding:
direction = (transform.basis * Vector3(slide_vector.x, 0, slide_vector.y)).normalized()
current_speed = (slide_timer + 0.1) * slide_speed
if direction:
velocity.x = direction.x * current_speed
velocity.z = direction.z * current_speed
else:
velocity.x = move_toward(velocity.x, 0, current_speed)
velocity.z = move_toward(velocity.z, 0, current_speed)
last_velocity = velocity
# RESPAWN
if position.y < -10.0:
position = Vector3(0, 0, 0)
last_velocity = Vector3.ZERO
move_and_slide()
free_looking
variable, and in the "sliding" part of the code you set it tofree_looking = false
, does changing to totrue
do what you want?