How to calculate a perfect counter force

end goal is to limit a vehicle’s slide by applying a counter force to the vehicle’s right and left at the wheel points, and for that i wont completly cancel the force, but a precentage of it, that’s why am looking for a way to calculate it

Cool! I would modify the equation like so

var right_vector: Vector3 = transform.basis.x
var right_plane_mask: Vector3 = Vecotr3.ONE - right_vector

var target_velocity: Vector3 = linear_velocity * right_plane_mask
const COUNTER_FORCE = 2.0 # m/s
linear_velocity = linear_velocity.move_toward(target_velocity, COUNTER_FORCE * delta)

I have never tried to make a realistic car, it always seems so daunting; so good luck! Hope I learned something :slight_smile:

i think this might be it, i’ll provide an update after testing it for a while
thanks for your time using these lines to cancel the velocity in a direction is a pretty genius idea

var right_vector: Vector3 = transform.basis.x
var right_plane_mask: Vector3 = Vecotr3.ONE - right_vector

well it seems i forgot the fact that i cant directly set linear_velocity since i need to control the friction of each wheel seperatly

If you haven’t seen it already there’s a seriously excellent video on car physics by the Very Very Valet devs on YouTube which could help you out. They split the forces applying to each wheel into 3 distinct parts.

There’s a closely related one on springs as well, which helped me greatly with the character controller I’m building.

A few notes on your problem:

  • I think this is understood already, but I found some of this thread confusing so to clarify - velocity isn’t a force, it’s a measure of speed and direction. Sorry for the pedantry but I want to make sure we’re trying to acheive the same thing. Forces (like gravity) represent acceleration/decelleration, not speed. Momentum is mass * velocity. I think you’re trying to find a force to partially cancel out (damp) the existing momentum, rather than to cancel out a force, but correct me if I have misunderstood.
  • I think @gertkeno’s suggestion of using apply_central_force is the way to go here. You should be able to apply it to your wheel using the wheel’s local right vector and some vector math (as in the video) if you want your wheel to have a harsher braking force when moving sideways. Or if you just want to cancel out the velocity on the wheel regardless of direction, you can apply some negative value * the current velocity. Using delta_time will keep it relatively framerate independant (but not fully).
  • Make sure to set a cap on the maximum counter-force that can be applied. Otherwise you can end up with physics bugs where eg. opposed forces oscillate and build, resulting in very high velocities, and very high forces that eventually reach near infinite velocity and break the physics engine.
  • Godot already applies some damping by default to all physics objects. This can be adjusted in the physics settings. It’s not a problem but could mess with your maths if you’re not aware of it.

this is infact the video i followed to code the car, but i had problems with the friction part, probably because of the differences between how godot and unity
handle forces and velocities

1-you are correct, am trying to find a way to calculate a force to partially and accurately cancel out the existing velocity in the wheels z basis, however simply using apply_force(-linear_velocity) doesnt work

2-as the video states, the wheel itself isn’t a seperate rigid body, there is only one rigid body being the car, and i simply apply the forces at the points the wheels exist, and as i said, simply applying the velocity in negative doesn’t work, as it seems godot calculates velocities and forces differently, i tried simply multiplying the velocity by -3 but i dont like this approach since it isnt very predictable, and it acts differently depending on car speeds

3-the cap should be the current wheels slide velocity, but i cant find a way to use it to calculate an accurate and predictable counter force

4-thanks, i will keep that in mind

Ah yeah. I’ve got to admit, it’s been a while since I actualy watched the video. Instead of the velocity of the wheel then you’ll need a velocity calculated for the wheel’s position based on the linear and angular velocities of the car, and the wheel’s position relative to the car. Then you’ll want to get the velocity in just the axis you are interested in (perpendicular to the wheel). If you’re not calculating that, that could be part of the difference.

I haven’t checked, but for a linear moving object I think
apply_central_impulse(-linear_velocity * mass);
or
apply_central_force((-linear_velocity * mass) / delta);
should stop an object dead. I’m not sure off the top of my head how to figure out what multiplier you need to get a desired stopping time, but you probably want to test it out for the best feeling stopping time anyway.

What formula do you have at the moment?

this is what i have right now

var SlideForce = get_point_velocity(Ray.global_position).project(Ray.global_basis.z)
var Interpration = RearGrip.sample(SlideForce.length() / (get_point_velocity(Ray.global_position).project(Ray.global_basis.x) + SlideForce).length())
var CounterSlide = -SlideForce * 0.25  * Interpration * mass / delta
draw_line(Ray.global_position, CounterSlide, true)
if linear_velocity.length() < SlowSpeed:
	apply_force(-SlideForce  * RearSlowGrip, Ray.global_position - global_position)
elif CounterSlide.length() <= 10**10:
	apply_force(CounterSlide, Ray.global_position - global_position) #the part where the force gets applied
#this code is applied 4 times for each wheel
#note that "Ray" is the suspension raycast, or the suspension point

problem is after dividing by delta the car becomes too grippy, even when i set the intereption to something as small as 0.3 the car still almost has full grip, but even with such high grip, when it goes at high speeds it cant maintain a straight line, and has a bit of sliding that makes it turn on its own

Ok so if I’m reading this right (and have correct assumptions about the functions without definitions):

SlideForce is the wheel’s sidewards velocity?
Interpration is (big assumption) a value from a lookup based on the ratio of the SlideForce’s magnitude and the wheel’s horizontal (non y-axis) movement?
At SlowSpeeds you use a constant multiplier for SlideForce, and at high speeds you use SlideForce. These forces are being applied at the (relative) position of the wheels?

Nothing here is screaming at me. Have you tried adding a few more draw_lines to check that each step of this calculation looks right in motion (this kind of stuff is difficult to debug by breakpoints and steps)?

I’d probably still apply a counterforce for very large forces, just a capped force (eg. using Clamp), but I doubt that’s your problem.

your assumptions are correct, and for testing purposes i made Interpration a still number

here’s a video explaining my issue further

Huh. Well this is a brain burner.

I guess it does make sense that at low speed there will be very little drift, and at high speeds there will be a lot, but it does look a bit extreme.

Are the acceleration and braking forces doing what you expect them to do? ie. only acting along one axis for each wheel.

I’m not sure I’m going to be much help getting to the bottom of this, I’d need to really dig into it and even then I’m pretty stumped right now. I’ll keep thinking on it though.

i would assume so

apply_force(Ray.global_basis.x * Acceleration * inverse_lerp(-SlowSpeed / 3, SlowSpeed, linear_velocity.length() + 1) * inverse_lerp(MaxSpeed, SlowSpeed, linear_velocity.length() + 1), Ray.global_position - global_position)
#note: acceleration is a number, in this case its equal to 10

Sure looks like it. And the “wheels” are facing the way they’re meant to be facing, not tilted in toward each other or something? I’m scraping at the barrel here I’m afraid. I guess you could try the same thing with Jolt, but I imagine it’ll be the same.

yeah, they’re facing the right way
the code previously used the car’s basis, and it results in the same
i even tried applying the acceleration force at 1 point being the middle point between the 2 rear wheels

How about at the car’s center of mass with apply_central_force?

Can you show a clip of what happens if you just accelerate in a straight line with no steering?

apply_central_force wouldn’t be very realistic, and i might run into another issue with the same core as this

as for the clip, what settings should i record it with (interplation and such)

It wouldn’t be realistic, but I’m just trying to root out the cause of the drift at high speed. Or, whatever it is that goes wrong. It sounds like maybe it just becomes a bit unstable?

I guess whatever settings you have now, or whichever ones you think best display the problem.

applying the force at the center of mass results in the same thing

here’s the clip:

(for internet reasons i will send the clip in a different reply in a few mins)

the same thing happens in the clip if i use apply central force instead
i even turned off the suspension springs part of the script to make sure they’re not the cause, and set the car’s friction to 0, again, same result

So it starts pulling right straight away, that was without steering input? You haven’t got a controller plugged in have you? Maybe it’s giving a small input?

The forces looked pretty huge though. Maybe it’s worth just accelerating in a straight line and putting a conditional breakpoint in (to trigger when the car is moving at X speed) so that you can more easily step through the code and check values once the car has started moving.