How to brake before backing up? (VehicleBody3D)

Godot 4.6.1

Please note that the “accelerate” input corresponds to moving forward, and the “brake” input corresponds to braking and moving backward.

In my case:

  • when “accelerate” input is released the brakes work (same for “brake” input is released)
  • when “accelerate” input is pressed and “brake” input too in the same time the brakes work (because the two cancel each other out)

But when “accelerate” input just released and “brake” input pressed just after that the brakes doesn’t work… I suppose that because my var moving_dir still !=0 and it never goes through zero.

How can I fix it please?

Here the script:

extends VehicleBody3D

@export var max_RPM = 1000
@export var max_torque = 2000
@export var turn_speed = 2
@export var turn_amount = 0.4

func _physics_process(delta: float) -> void:
	
	var forward = Input.get_action_strength("accelerate") 
	var backward = - Input.get_action_strength("brake")
	var moving_dir = forward + backward
	
	var turn_left = Input.get_action_strength("left")
	var turn_right = - Input.get_action_strength("right")
	var steering_dir = turn_left + turn_right
	
	var RPM_left = abs($BackL.get_rpm())
	var RPM_right = abs($BackR.get_rpm())
	var RPM = (RPM_left + RPM_right) / 2.0
	
	var torque = moving_dir * max_torque * (1.0 - RPM / max_RPM)
	
	engine_force = torque
	steering = lerp(steering, steering_dir * turn_amount, turn_speed * delta)
	
	if moving_dir == 0 :
		brake = 50

Thanks for your time!

float variables are rarely exactly 0 due to the very nature of floating numbers. That’s why is_zero_approx() exists.

Thanks for your answer, in practice how integrate this in my script?

if moving_dir.is_zer_approx()

Sorry I’m new in coding world!

It should rather be
if is_zero_approx(moving_dir):

It doesn’t seem to make any difference, if you press the brake button right after releasing the accelerator button, it doesn’t brake :frowning:

(It takes more time to slow down than when accelerator just released)

Try adding some print() statements to your code to understand the state of your variables.

I’m a beginner, so I don’t know where to put print() statements or how that might help me understand my problems or errors…

I’m having trouble understanding how to add and check my vehicle’s inertia. Right now, in my code, I only have a positive or negative value for the direction, but nothing regarding the inertia of the VehicleBody3D node. So I think that if I can determine when the inertia is positive and apply a negative direction to it, the vehicle will first brake, then move in the negative direction (backward).

Is this bad logic, or am I missing something?

Here the solution:

extends VehicleBody3D

@export var max_RPM = 1000
@export var max_torque = 2000
@export var turn_speed = 2
@export var turn_amount = 0.4

@export var engine_brake = 50.0
@export var hard_brake = 100.0

func _physics_process(delta: float) -> void:

     var move_forward = Input.get_action_strength("accelerate")
     var move_backward = Input.get_action_strength("brake")
     var throttle = move_forward - move_backward

     var move_left = Input.get_action_strength("left")
     var move_right = Input.get_action_strength("right")
     var turn = move_left - move_right

     var RPM_left = $BackL.get_rpm()
     var RPM_right = $BackR.get_rpm()
     var signed_RPM = (RPM_left + RPM_right) / 2.0
     var abs_RPM = abs(signed_RPM)

     if is_zero_approx(throttle):
          brake = engine_brake
          engine_force = 0.0

     elif (throttle > 0 and signed_RPM < -10.0) or (throttle < 0 and signed_RPM > 10.0):
          brake = hard_brake
          engine_force = 0.0

     else:
          brake = 0.0
          engine_force = throttle * max_torque * (1.0 - abs_RPM / max_RPM)

     steering = lerp(steering, turn * turn_amount, turn_speed * delta)

Have fun, be creative, stay curious - see you!