Implementing Simple Cart Physics?

Hi there,

I have been looking for a simpler solution than the realistic car based physics tutorials out there. I am working on a game with carts requiring only a simple physics system and the driving may not be realistic. So far i have implemented the following code
using UnityEngine;
using System.Collections;

/**

  • Simple “cart” based physics system for moving carts controlled

  • by a user player.
    */
    public class CartMovementControl : MonoBehaviour {

    // every wheel contains useful wheel specific info
    public struct Wheel {
    public Transform transform;
    public GameObject go;
    public Rigidbody body;
    public bool turn;
    public float rotation;
    public float maxSteer;
    public float radius;
    public Vector3 previousLocation;
    };

    //cart properties
    public float speed = 45;
    public float maxSpeed;
    public float rotateSpeed;
    public float trueMaxSpeed;
    public float maxSteerAngle = 30;
    public float steeringRadius = 15;

    //public access state variables
    public Vector3 cartLocation; // location of the center of the car
    public Vector3 cartHeading; // current direction of the car
    public float wheelBase; // distance between front and back wheels of the car

    //wheels
    public Wheel wheels;
    public GameObject wheelFL;
    public GameObject wheelFR;
    public GameObject wheelBL;
    public GameObject wheelBR;
    public float frontLeftRadius;
    public float frontRightRadius;
    public float backLeftRadius;
    public float backRightRadius;
    public RearWheelCollider rwc;

    //input
    public float turning;
    public float accel;
    public float brake;
    public bool reverse;

    void Update () {
    turning = Mathf.Clamp(Input.GetAxis(“Horizontal”), -1, 1);
    accel = Mathf.Clamp(Input.GetAxis(“Vertical”), 0, 1);
    brake = -1 * Mathf.Clamp(Input.GetAxis(“Vertical”), -1, 0);

      if (rigidbody.velocity.sqrMagnitude == 0) {
      	if (brake > 0) { reverse = true; }
      	if (accel > 0) { reverse = false; }
      }
      
      if (reverse) { accel = -1*brake; }
      
      //turning should rotate any of the "turning wheels" (typically front)
      rotateCartDirection(turning);
      
      //acceleration needs be calculated along (with drag?)
      calculateCartAcceleration(accel);
    
      //rotate the cart wheels
      rotateCartWheels();
    

    }

    void Start() {
    rigidbody.centerOfMass = new Vector3(0, -1.5f, 0);
    rwc = GameObject.Find(“RearWheels”).GetComponent();
    trueMaxSpeed = maxSpeed * maxSpeed;
    //setup the wheel structs for each wheel object
    wheels = new Wheel[4];
    wheels[0] = setupWheelParameters(wheelFL, frontLeftRadius, true);
    wheels[1] = setupWheelParameters(wheelFR, frontRightRadius, true);
    wheels[2] = setupWheelParameters(wheelBL, backLeftRadius, false);
    wheels[3] = setupWheelParameters(wheelBR, backRightRadius, false);
    }

    void calculateCartAcceleration(float accel) {
    print(accel);
    if (Mathf.Abs(accel) < 0.15 || !rwc.isGrounded) return;
    Vector3 direction = transform.forward;
    if (accel < 0) {
    direction = -transform.forward;
    accel = -1 * accel;
    }
    rigidbody.AddForce(direction * accel * speed * 100);
    var v = rigidbody.velocity; // current speed
    // for limiting kart max speed
    if(v.sqrMagnitude >= trueMaxSpeed){ // truemaxspeed is the max speed * max speed.
    rigidbody.velocity = v.normalized * maxSpeed;
    }
    }

    void rotateCartDirection(float turning) {
    //we cannot rotate the cart when it is not grounded (but can rotate the wheels)
    if (rwc.isGrounded) {
    float cartRotate = turning * steeringRadius * Time.deltaTime * rotateSpeed;
    transform.Rotate(0, cartRotate, 0);
    }

      //now apply additional rotations to the wheels
      foreach (Wheel wheel in wheels) {
          float rotateAngle = turning * wheel.maxSteer; //will be 0 if the wheel is not a turning wheel
      	wheel.transform.localRotation = Quaternion.Euler(0, rotateAngle, 0);
      }
    

    }

    void rotateCartWheels() {
    for (int i = 0; i < wheels.Length; i++) {
    if (!rwc.isGrounded) {
    //in the air so just rotate freely at the maximum speed
    Wheel wh = wheels*;*

  •   		wh.transform.Rotate(rigidbody.velocity.x, 0, 0);*
    
  •   	} else {*
    

_ //distance travelled = radius * angle of rotation_
_ Wheel wh = wheels*;_
_
Vector3 dist = wh.transform.position - wh.previousLocation;_
_
double rad = wh.transform.localScale.y / 2.0;_
_ float xrotation = (float)((dist.x/rad) * rigidbody.velocity.x);_
_
wh.transform.Rotate(xrotation, 0, 0);_
_
wh.previousLocation = wh.transform.position;_
_
}_
_
}_
_
}*_

* Wheel setupWheelParameters(GameObject wheel, float radius, bool turn) {*
* Wheel result = new Wheel();*
* result.go = wheel;*
result.transform = wheel.transform;
result.body = wheel.rigidbody;
result.radius = radius;
result.turn = turn;
if (turn)
result.maxSteer = maxSteerAngle;
else
result.maxSteer = 0;
* result.previousLocation = wheel.transform.position;*
return result;
* }*
}
This works fine for moving the cart around and rotating the wheels.
I would like to know how I should implement some form of drag on the cart so it slows down due to friction with the road? Also is there any better way to implement the forward force (currently using the rigidbody.addForce(transform.foward…) method however this will not reduce force in any direction - currently the car can move forward and then rotate 90 degrees while still travelling forward. Also is there a way to stop the car rotating on the spot?
Any advice would be appreciated

if you want the cart to turn only when it is moving make the turning force a function of speed and play with the parameters a bit to get it right