Need help with disabling crouch while mid air

4.2

Question

Hello guys so I have a little problem with my character script it is that i need it to crouch jump which works good enough and i need it to not have the ability to crouch after i jumped or if i am mid air

here is the script

extends CharacterBody3D

Player nodes

@onready var neck: Node3D = $neck
@onready var head =$neck/head
@onready var eyes: Node3D = $neck/head/eyes
@onready var standing_collision_shape: CollisionShape3D = $standing_collision_shape
@onready var crouching_collision_shape: CollisionShape3D = $crouching_collision_shape
@onready var ray_cast_3d: RayCast3D = $RayCast3D
@onready var camera_3d: Camera3D = $neck/head/eyes/Camera3D

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 = 10.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

var crouching_depth = -0.5

const jump_velocity = 4.5

var lerp_speed = 10
var air_lerp_speed = 3

var free_look_tilt_amount = 8

Input vars

var direction = Vector3.ZERO

const mouse_sens = 0.25

func _ready():
Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)

func _input(event: InputEvent) → void:
# 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 _process(delta):
if Input.is_action_just_pressed(“quit”):
get_tree().quit()

func _physics_process(delta: float) → void:
# 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)
	
	standing_collision_shape.disabled = true
	crouching_collision_shape.disabled = false
	
	# Slide begin logic
	
	if sprinting && input_dir != Vector2.ZERO:
		sliding = true
		slide_timer = slide_timer_max
		slide_vector = input_dir
		free_looking = true
		print("slide begin")
	
	walking = false
	sprinting = false
	crouching = true
	
elif !ray_cast_3d.is_colliding():
	
# Standing
	standing_collision_shape.disabled = false
	crouching_collision_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:
		camera_3d.rotation.z = lerp(camera_3d.rotation.z,-deg_to_rad(7.0),delta*lerp_speed)
	else:
		camera_3d.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)
	camera_3d.rotation.z = lerp(camera_3d.rotation.z,0.0,delta*lerp_speed)

# Handle sliding

if sliding:
	slide_timer -= delta
	if slide_timer <= 0:
		sliding = false
		print("slide end")
		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)
	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)
	

# Add the gravity.
if not is_on_floor():
	velocity += get_gravity() * delta

# Handle jump.
if Input.is_action_just_pressed("ui_accept") and is_on_floor and !ray_cast_3d.is_colliding():
	velocity.y = jump_velocity
	sliding = false
	

# 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)

move_and_slide()

Hello @youssefspider20! So, I think you can use is_on_floor() method. Just check when player has been call action crouch. For example, based on your code:

if Input.is_action_pressed("crouch") || sliding:
     # Check player is on floor at this moment
     if not is_on_floor():
         # Player is not on floor
         return
      
     # Player is on floor
     current_speed = lerp(current_speed,crouching_speed,delta*lerp_speed)
     # Crouch code...

I’m not sure about that, but you can give it a try.