I have recently started creating custom car physics in Godot and I was wondering if it's possible to calculate a drag force/speed cap with a pre-established top speed. I want to do this without manually changing the velocity of the RigidBody. Any help is appreciated.
Calculating drag force for a car with a top speed in mind
- Edited
I use a PID controller for this in my 2D platformer player character, that I managed to implement from this Unity tutorial:
extends Node
class_name PIDController
@export var proportional_gain: float = 1
@export var integral_gain: float = 0
@export var derivative_gain: float = 0.1
var p: float
var d: float
var i: float
@export_enum("Derivative of Value", "Derivative of Error") var derivative_measurement_mode: int
var current_err: float
var last_err: float
var d_of_err : float
var last_val: float
var d_of_val: float
var d_initialised: bool = false
var integration_stored: float
@export var integration_saturation: float = 1
func _get_output(_delta: float, _current_val: float, _target_val: float,
_min: float, _max: float
) -> float:
current_err = _target_val - _current_val
p = proportional_gain * current_err
d_of_err = (current_err - last_err) / _delta
last_err = current_err
d_of_val = (_current_val - last_val) / _delta
last_val = _current_val
if d_initialised == true:
if derivative_measurement_mode == 1:
d = derivative_gain * d_of_val
else:
d = derivative_gain * d_of_err
else:
d_initialised = true
d = 0
integration_stored = clamp(integration_stored + (current_err * _delta),
-integration_saturation, integration_saturation
)
i = integral_gain * integration_stored
return clamp(p + d + i, _min, _max)
func _reset():
d_initialised = false
I attach this script to rigidbodies and tune them individually in the inspector ((Edit: In my case, as probably should be in yours, I guess, the integral gain is set to zero)), then call _get_output()
through a reference in the rigidbody scripts with parameters:
_delta
: which is thedelta
of_process(delta)
or_physics_process(delta)
in which the method is called_target_val
: which is the value I want my one of my rigidbody's properties to match (your car's maximum velocity)_current_val
: which is the current value of property that I want to be equal to_target_val
(your car's velocity)_min
and_max
: which are the minimum and maximum values the controller can output. In my case it's plusminus the maximum acceleration I want my player to move with. Your game is in 3D, so it's something else (It could plausibly be max acceleration while reversing to max forward acceleration. This stuff is powerful ^^)
Anywho, hook all that up to a apply_central_force()
. I'm still kinda new to Godot, so there could be sum errors and inefficiency ^_^; so make changes as it suits you c: