I can't make Dash for FPS games

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By Silence_XG

I’m trying to make a movement for a demo of my FPS game, and I ran into the problem that the Dash version I created, for some reason, only works when the character model does not touch the floor.

I am new to Good, so I will be very grateful for as detailed an answer as possible, if you have one. Thank you in advance

extends CharacterBody3D

const SPEED = 10
const JUMP_VELOCITY = 10
const SENSAVITY = 0.005
const SHIFT = 30

var gravity = 20

@onready var head = $Head
@onready var camera = $Head/Camera

func _ready():
	Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
 
func _unhandled_input(event):
	if event is InputEventMouseMotion:
		head.rotate_y(-event.relative.x * SENSAVITY)
		camera.rotate_x(-event.relative.y * SENSAVITY)
		camera.rotation.x = clamp(camera.rotation.x, deg_to_rad(-90), deg_to_rad(100))

func _physics_process(delta):
	
	if not is_on_floor():
		velocity.y -= gravity * delta

	if Input.is_action_just_pressed("ui_accept") and is_on_floor():
		velocity.y = JUMP_VELOCITY

	var input_dir = Input.get_vector("ui_left", "ui_right", "ui_up", "ui_down")
	var direction = (head.transform.basis * Vector3(input_dir.x, 0, input_dir.y)).normalized()

	
	if Input.is_action_just_pressed("ui_shift"):
		if direction:
			velocity.x = direction.x * SHIFT
			velocity.z = direction.z * SHIFT

	if is_on_floor():

		if Input.is_action_just_pressed("ui_shift"):
			if direction:
				velocity.x = direction.x * SHIFT
				velocity.z = direction.z * SHIFT
	
		if direction:
			velocity.x = direction.x * SPEED
			velocity.z = direction.z * SPEED

		else :
			velocity.x = lerp(velocity.x, direction.x * SPEED, delta * 10.0)
			velocity.z = lerp(velocity.z, direction.z * SPEED, delta * 10.0)

	else:
		velocity.x = lerp(velocity.x, direction.x * SPEED, delta * 3.0)
		velocity.z = lerp(velocity.z, direction.z * SPEED, delta * 3.0)

	move_and_slide()
:bust_in_silhouette: Reply From: zhyrin

No matter whether you pressed shift or not, the velocity gets rewritten with a speed multiplication anyway. You should put an else before the second if direction:.

if is_on_floor():

    if Input.is_action_just_pressed("ui_shift"):
        if direction:
            velocity.x = direction.x * SHIFT
            velocity.z = direction.z * SHIFT

    if direction:
        velocity.x = direction.x * SPEED
        velocity.z = direction.z * SPEED

An even better solution would be to rewrite the code a bit.
First, I would rename the SHIFT constant to DASH_SPEED.
Second, velocity.x = direction.x * <SPEED/SHIFT> occurs multiple times, you should put the multiplier value in a separate variable and have this statement only once.

var speed_multiplier = SHIFT if Input.is_action_just_pressed("ui_shift") else SPEED
velocity.x = direction.x * speed_multiplier
<same for z axis>

Same for lerping.

Your advice helped a lot. Thank you very much. I really didn’t notice such an obvious moment.

I tried to rewrite the code according to your recommendations, but I ran into another problem. Dash speeds in the air and on the floor are different. And I would like to make this value the same.

if is_on_floor():
	
	var speed_multiplier = SHIFT if Input.is_action_just_pressed("ui_shift") else SPEED
	if direction:
		velocity.x = direction.x * speed_multiplier
		velocity.z = direction.z * speed_multiplier

	else:
		velocity.x = lerp(velocity.x, direction.x * speed_multiplier, delta * 10.0)
		velocity.z = lerp(velocity.z, direction.z * speed_multiplier, delta * 10.0)

if not is_on_floor():
	
	var speed_multiplier = SHIFT if Input.is_action_just_pressed("ui_shift") else SPEED
	if Input.is_action_just_pressed("ui_shift"):
		if direction:
			velocity.x = direction.x * speed_multiplier
			velocity.z = direction.z * speed_multiplier
	
	else:if direction:
			velocity.x = lerp(velocity.x, direction.x * speed_multiplier, delta * 20.0)
			velocity.z = lerp(velocity.z, direction.z * speed_multiplier, delta * 20.0)

Silence_XG | 2023-07-04 16:36

You have a section where you lerp if you are on the floor, and in another if you are in the air. In these sections the lerp value is different, delta * 10.0 in the first, delta * 20 in the second.

zhyrin | 2023-07-06 08:32