Help with making player character skid/slide after stopping

Godot Version

Godot 4.7

Question

hello again! i’m currently working on a small game that uses overhead 2D tank controls. though i’ve looked into a few ways to add skidding/sliding after the movement input’s stopped, none have managed to work. it might be the way my movement’s set up? unsure.

regardless, here’s the relevant code (unimportant things not related to movement have been cut) :

extends CharacterBody2D

[...]


@export var speed: float = 50.0
@export var turn_speed: float = 5.0
@export var max_speed: float = 115.0
@export var acceleration: float = 0.5
@export var drag: float = 10

var rotation_direction = 0

[...]

func _physics_process(delta: float) -> void:
	get_input()
	rotation += rotation_direction * turn_speed * delta
	
	if Input.get_axis("move up", "move down"):
		if speed < max_speed:
			speed += acceleration
		else:
			speed = max_speed
	else:
		speed = 50.0
	
	if not Input.get_axis("move up", "move down"):
			velocity.x = move_toward(speed, 0, drag)
			velocity.y = move_toward(speed, 0, drag)
   #the above was my attempt to copy other peoples' move_toward sliding/skidding solutions. it just moved the character to the lower right.
	print(speed)
	
	[...]
	
	[...]
	
	move_and_slide()

func get_input():
	rotation_direction = Input.get_axis("turn left", "turn right")
	velocity = transform.y * Input.get_axis("move up", "move down") * speed

thank you for reading! please let me know if i should add anything else to make things clearer.

It’s probably better to increase velocity towards speed by acceleration rather than the two-step process of adding to speed

It’s also worth noting by not using delta your calculations are per-frame rather than per-second so the character will move faster on faster computers. but _physics_process should run at a fixed rate.

func _physics_process(delta: float) -> void:
	var rotation_direction := Input.get_axis("turn left", "turn right")
	rotation += rotation_direction * turn_speed * delta
	
	var input_y := Input.get_axis("move up", "move down")
	var target_speed: Vector2 = transform.y * input_y * speed
	velocity = velocity.move_toward(target_speed, acceleration * delta)

	move_and_slide()

I think this snippet would provide the functionality you want, but with delta you will need to adjust your acceleration and maybe speed values much higher.

I don’t use drag in this sample, it seems odd as you would stop faster by releasing the y input than you would by moving it in the opposite direction, without drag the acceleration and deceleration are the same. You could make deceleration faster after detecting a backwards input, this can be found with a dot product of the input and velocity, if it’s negative then the input is moving away from velocity.

This is not true for _physics_process()! If the movement calculations were happening in _process(), then your statement would be correct._physics_process() runs at a fixed rate and _process() runs on every rendered frame.

Relevant docs page: Idle and Physics Processing — Godot Engine (stable) documentation in English

Using delta in _physics_process() is still advisable in case you end up changing your project’s physics tickrate at some point.

this works perfectly, thank you! i think i will still make putting an opposite input decelerate faster, but this is a great slide o/