How to gradually increase car speed that's related to the vertical input instead of doing it instantly?

I have a simple controller for moving a car around. For accelerating and reversing, I use the following logic:

private void HandleVehicleAcceleration()
{
    if (accelControl > 0)
        speedInput = accelControl * VehicleForwardSpeed * 1000f;
    else if (accelControl < 0)
        speedInput = accelControl * VehicleReverseSpeed * 1000f;
}

Here, accelControl represents the vertical input axis. speedInput starts with a value of 0. When used, speedInput is applied to the car via Rigidbody.AddForce() in a separate method.

With this code, speedInput, when using or releasing the vertical input axis, goes from 0 to 1000 instantly. How can I make speedInput get its value more gradually?

Smoothing the change between any two particular values:

You have currentQuantity and desiredQuantity.

  • only set desiredQuantity
  • the code always moves currentQuantity towards desiredQuantity
  • read currentQuantity for the smoothed value

Works for floats, Vectors, Colors, Quaternions, anything continuous or lerp-able.

The code: SmoothMovement.cs · GitHub

I implemented the base logic from your script into my code:

private void HandleVehicleAcceleration()
{
    float targetSpeed = 0f;

    if (accelControl > 0)
        targetSpeed = accelControl * VehicleForwardSpeed * 1000f;
    else if (accelControl < 0)
        targetSpeed = accelControl * VehicleReverseSpeed * 1000f;

    speedInput = Mathf.MoveTowards(speedInput, targetSpeed, 2.0f * Time.deltaTime);
}

The problem that I run into now is that the car won’t move at all; debugging speedInput shows that it’s always a very low value. What am I doing wrong here?

debug what everything else is too!!!

PRINT ALLLLLL THE THINGS…

By debugging you can find out exactly what your program is doing so you can fix it.

Use the above techniques to get the information you need in order to reason about what the problem is.

You can also use Debug.Log(...); statements to find out if any of your code is even running. Don’t assume it is.

Once you understand what the problem is, you may begin to reason about a solution to the problem.

Remember with Unity the code is only a tiny fraction of the problem space. Everything asset- and scene- wise must also be set up correctly to match the associated code and its assumptions.

I think the 2.0f * Time.deltaTime is probably the problem.
I think by default this will change speedInput by 2 per second. I’d set the 2.0 to be some field you can set in the editor, and just crank it up until you get the feel you want.
While I’m writing, I’m guessing you’re doing the AddForce from FixedUpdate (good!), and if you’re using the old input system, I believe you should read inputs from Update.

I did some general advice about car physics in Unity a while ago.

1 Like

By sheer coincidence, I followed that exact same tutorial that you linked in your post! I also watched the tutorial that OOP showed and I came up with this:

private void HandleVehicleAcceleration()
{
    float currentSpeed = Vector3.Dot(transform.forward, VehicleBody.linearVelocity);
    float normalizedSpeed = Mathf.Clamp01(Mathf.Abs(currentSpeed) / VehicleMaxSpeed);
    float availableTorque = VehiclePowerCurve.Evaluate(normalizedSpeed);

    if (accelControl > 0)
    {
        accelControl *= VehicleForwardForce * 1000f;
        availableTorque *= accelControl;
    }
    else if (accelControl < 0)
    {
        accelControl *= VehicleReverseForce * 1000f;
        availableTorque *= accelControl;
    }
    else
        transform.position = transform.InverseTransformDirection(VehicleBody.GetPointVelocity(transform.forward));


    speedInput = availableTorque * transform.forward;
}

After changing AddForce and toying with car values I managed to make it accelerate gradually using animation curves. All that’s left to do now is to figure out how can I “flip” the curve when accelControl is 0 so I can simulate engine braking

EDIT: I managed to implement engine braking, didn’t even need to reuse the anim curve. If anyone comes up to this post in the future, feel free to use this!

2 Likes