How can I use an input axis in an animation curve and delay how fast AnimationCurve.Evaluate works?

Hello, first of all, I’m a total noob when it comes to programing, I’m trying to make some car physics and I need to control the RPM somehow when the car is not moving. I figured I could do it just like how it basically works in real life: if you step on the gas the RPM goes up. I thought I could use an animation curve to make this happen, since I used this for the torque curve too. In theory I would set the idle RPM as the lowest value(which would mean input is 0) and max RPM as the highest value(input is 1). After that I would need to take into account engine friction and the flywheel inertia, but I’m stuck at this point. How could I control how fast or slow the RPM goes up. Time.deltaTime doesn’t really work how I used it(which is simply multiplying it). Right now if I press the gas I get instant max RPM. What I have right now is:

public float input;
public float idleRPM;
public float maxRPM;
public float currentRPM;
public float torque;
public float friction;
public float inertia;

public AnimationCurve engineSpeed;
public AnimationCurve torqueCurve;

private void Start()
{
engineSpeed.AddKey(0, idleRPM);
engineSpeed.AddKey(1, maxRPM);
}

// Update is called once per frame
void FixedUpdate()
{
input = Input.GetAxis(“Accel”);

currentRPM = engineSpeed.Evaluate(input);
torque = torqueCurve.Evaluate(currentRPM);
}
Basically an on/off switch. Multiplying by anything just raises/lowers the max RPM. I can already see a big no-no with this approach, which is when going uphill the RPM should go down and in this case I don’t think it will. I’ll probably use the wheel RPM to calculate engine RPM while moving or a median of the two values. Anyway can anyone help me on this? or recommend another approach?

I applaud your current approach of using an AnimationCurve to drive all this.

What you still need to do however is move the input value smoothly from zero to maximum (usually 0 to 1 to keep things simple across the board) at a specific speed.

What that means is that your current code that takes the input values and directly uses it to look up RPM needs to change. One alternate approach is to:

  • get the input and assign that to “my desired RPM.”

  • every frame adjust another variable that is “my current RPM” up or down until it reaches the desired RPM

  • Finally you would use the “current RPM” to look up the actual RPM off a curve.

Now alternately you could involve your torque curve to drive how fast up/down the RPM goes. I recommend waiting on this and getting the simplest way working first because stacking curves like that can make balance/tuning tricky.

Using a far simpler approach WITHOUT animation curves, this is how I did my slick track racer engine code.

First I have some engine parameters:

acceleration
braking
turning

Second I keep a notion of your current vehicle velocity. I am doing all the physics myself.

When you hit the gas it steadily accelerates you by adding to your current facing direction according to how big your acceleration is.

When you let off the gas there is a gentle engine braking, and when you hit the brakes the deceleration term is used to slow you.

And finally when you turn it uses the turning term to decide how much lateral turning you’re really gonna get, versus sliding around the track.

This is what it plays like, placeholder audio and graphics for now:

It’s super-simple controls but man it’s fun to drift about. I hope to make it into a complete game some day.

Thanks for the ideas. What I ended up doing is lerping between min and max RPM by Time.deltaTime. I completely forgot about lerping. Also there is a smoothdamp function, which I believe works somewhat similarly, but I haven’t looked into it.

1 Like