2D Car Physics for Drag Race Game

Hello there!

I’m trying to develop a 2D drag race game so I need to code a simple but (almost) realistic physics system for the car. In a drag race the car just needs to go straight forward as fast as it can, so I don’t need to handle braking or curves.

I’m following this tutorial and it helped me a lot: Car Physics

I already wrote some code and it seems to work properly as long as I don’t change gear. In fact as soon as I insert the 2nd gear, acceleration becomes negative and so the car slows down, so I’m basically trying to understand what I did wrong.

This is the code I wrote so far and my torque curve. Thank you to anyone who will help me a bit with this!

[RequireComponent(typeof(Rigidbody2D))]
public class CarController : MonoBehaviour
{
    #region CONSTANTS

    private const float c_friction = 0.3f;
    private const float c_frontalArea = 2.2f;
    private const float c_airDensity = 1.9f;
    private const float c_efficiency = 0.7f;

    #endregion

    #region PRIVATE

    private Rigidbody2D _rb;

    private Vector2 _velocity;
    private Vector2 _lastVelocity;

    private Vector2 _position;
    private Vector2 _lastPosition;

    private Vector2 _direction => this.transform.right;
    private Vector2 _traction => this._direction * this._driveForce;
    private Vector2 _drag => -this._dragCoef * this._velocity * this._velocity.magnitude;
    private Vector2 _rolling => -this._rollingCoef * this._velocity;
    private Vector2 _logitude => this._traction + this._drag + this._rolling;
    private Vector2 _driveForce => this._direction * this.TorqueAtRpm(this._rpm) * this.GearMultiplier() * CarController.c_efficiency / this.wheelRadius;
    private Vector2 _acceleration => this._logitude / this.mass;

    private float _dragCoef => 0.5f * CarController.c_friction * CarController.c_frontalArea * CarController.c_airDensity * this._speed;
    private float _rollingCoef => 30f * this._dragCoef;
    private float _wheelRotationRate => this._velocity.x / this.wheelRadius;
    private float _wheelAcceleration => this.TorqueAtRpm(this._rpm) * this.GearMultiplier() * CarController.c_efficiency;

    private float _rpm;
    private float _speed;

    private int _currentGear = 1;

    #endregion

    #region GETTERS

    private float GearRatio(int p_gear = 0)
    {
        return this.gearRatios[p_gear == 0 ? this._currentGear : p_gear - 1];
    }

    private float GearMultiplier(int p_gear = 0)
    {
        return this.GearRatio(p_gear) * this.differentialRatio;
    }

    private float TorqueAtRpm(float p_rpm)
    {
        return this.torqueCurve.Evaluate(p_rpm);
    }

    #endregion

    public AnimationCurve torqueCurve;

    [Space]

    public float minRPM; //700
    public float maxRPM; //8000

    [Space]

    public float mass; //1465 (kg)
    public float wheelRadius; //0.34 (m)

    [Space]

    public float[] gearRatios; //{ 3.08, 2.19, 1.63, 1.29, 1.03, 0.84, 0.69 }
    public float differentialRatio; //4.37

    private void Awake()
    {
        this._rb = this.GetComponent<Rigidbody2D>();
    }

    private void Update()
    {
        if (Input.GetKeyDown(KeyCode.UpArrow))
        {
            if (this._currentGear < this.gearRatios.Length - 1)
            {
                this._currentGear++;
            }
        }
    }

    private void FixedUpdate()
    {
        this._velocity = this._lastVelocity + Time.fixedDeltaTime * this._acceleration;

        if(this._lastVelocity != this._velocity)
        {
            this._lastVelocity = this._velocity;
        }

        this._position = this._lastPosition + Time.fixedDeltaTime * this._velocity;

        if(this._lastPosition != this._position)
        {
            this._lastPosition = this._position;
        }

        this.GetRPM();

        this._rb.AddForce(this._driveForce, ForceMode2D.Force);

        this._speed = Mathf.Sqrt(Mathf.Pow(this._velocity.x, 2) + Mathf.Pow(this._velocity.y, 2)) * 3.6f;
    }

    private void GetRPM()
    {
        this._rpm = this._wheelRotationRate * this.GearMultiplier() * 60f / Mathf.PI;

        if (this._rpm < this.minRPM)
        {
            this._rpm = this.minRPM;
        }

        if(this._rpm > this.maxRPM)
        {
            this._rpm = this.maxRPM;
        }
    }

}
1 Like

I don’t need any code. I just need some mathematical equations. Equations similar to these: If my instantaneous acceleration, velocity and engine power is this much where should my car be located in the next tick? I just want some ideas on the algorithms/equations. I don’t want a full fledged research. All I am hoping for is that anybody who already knows some equations and/or algorithms about a certain aspect of drag racing can let everyone know about that in an answer. I am hoping to make something out of the answers I receive. To begin, I have posted an answer to my own question.

TellTims.com

Hi, I have a similar problem, do you think you could provide the program/code how you solved it? Thanks.