Handling Friction/Acceleration with a CharacterBody3D for a 3D Platformer

Godot Version

Using Godot Version 4.2.

Experience

Beginner, I barely have a clue as to what I’m doing

Question

Hello! I am trying to work on a 3D platformer, taking cues specifically from Sonic Adventure in particular, and I have been using a CharacterBody3D. I’ve been using a modified version of the default sample code, and I’m not sure how to get character acceleration and deceleration working smoothly.
Here’s a snippet of the character movement code, if needed I can provide the full code:

var MAXSPEED = 30.0
var SPEED = 0.0
var JUMP_VELOCITY = 16.0
var DECEL = 0.40
var ACCEL = 0.20

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

	var input_dir = Input.get_vector("move_left", "move_right", "move_forward", "move_backward")
	var direction = (twist_pivot.basis * transform.basis * Vector3(input_dir.x, 0, input_dir.y)).normalized()
	if direction:
		# Speed up acceleration
		velocity.x = direction.x * SPEED
		velocity.z = direction.z * SPEED
		if SPEED < MAXSPEED:
			SPEED = SPEED + ACCEL
		print("SPEED:",SPEED)
	elif SPEED > 0:
		# Slow down
		SPEED = SPEED - DECEL
		velocity.x = move_toward(velocity.x, SPEED, 0)
		velocity.z = move_toward(velocity.z, SPEED, 0)
		print("SPEED:",SPEED)
	else:
		# Stop
		SPEED = 0
		velocity.x = move_toward(velocity.x, 0, MAXSPEED)
		velocity.z = move_toward(velocity.z, 0, MAXSPEED)
	move_and_slide()

If anybody could provide a explanation as to how I could polish up the acceleration/deceleration, please do tell me. As well, if the full code is needed: I can provide that as well.

If the last value is the delta amount then this code will not change any value since the delta is 0.

It’s the same as

velocity.x = velocity.x

All caps usually is a const value in practice, so to not treat it as such will make your life difficult as the value will change over time beyond it’s defined starting value. Maybe it not intended to be const, but the all caps as const is standard practice. Just made me a little confused.

If you want a non-linear curve look into using the global ease or smoothstep function or the vector2 function slerp.

Yes the ease and smooth step are floats only, but I mean for you to apply them as the delta to force the linear move_toward function to behave differently over time.

When slowing down, the target should be zero and your delta can be some fixed constant for a linear deceleration. I don’t think you need the else stop case. Unless you really want a hard stop but that should be nested in the declaration code as a threshold velocity check to snap to 0.

1 Like

Thank you for the response! I’ll try and see what I can do based on your response, this does help quite the bit.