This is part of an ongoing mission to explore making a simple controlled vehicle using the Unity Wheel Collider. See the introduction for a chapter list.

When I posted my first wheel collider demo to the Unity forum I got some really good feedback. So now I updated my scene and script to iron out odd behaviours and add new features. I have posted the scene in a web player and the complete updated script again.

For completeness sake here is the updated script.

var rearWheel1 : WheelCollider;
var rearWheel2 : WheelCollider;
var frontWheel1 : WheelCollider;
var frontWheel2 : WheelCollider;

var wheelFL : Transform;
var wheelFR : Transform;
var wheelML : Transform;
var wheelMR : Transform;
var wheelRL : Transform;
var wheelRR : Transform;

var steer_max = 20;
var motor_max = 40;
var brake_max = 100;
var steerSpeed = 20;

private var steer = 0;
private var forward = 0;
private var back = 0;
private var brakeRelease = false;
private var motor = 0;
private var brake = 0;
private var reverse = false;
private var speed = 0;

function Start() {
rigidbody.centerOfMass = Vector3(0, -0.05, 0);
}

function FixedUpdate () {

speed = rigidbody.velocity.sqrMagnitude;
steer = Input.GetAxis("Horizontal");
forward = Mathf.Clamp(Input.GetAxis("Vertical"), 0, 1);
back = -1 * Mathf.Clamp(Input.GetAxis("Vertical"), -1, 0);

if(speed == 0 && forward == 0 && back == 0) {
brakeRelease = true;
}

if(speed == 0 && brakeRelease) {
if(back > 0) { reverse = true; }
if(forward > 0) { reverse = false; }
}

if(reverse) {
motor = -1 * back;
brake = forward;
} else {
motor = forward;
brake = back;
}
if (brake > 0 ) { brakeRelease = false; };

rearWheel1.motorTorque = motor_max * motor;
rearWheel2.motorTorque = motor_max * motor;
rearWheel1.brakeTorque = brake_max * brake;
rearWheel2.brakeTorque = brake_max * brake;

if ( steer == 0 && frontWheel1.steerAngle != 0) {
if (Mathf.Abs(frontWheel1.steerAngle) <= (steerSpeed * Time.deltaTime)) {
frontWheel1.steerAngle = 0;
} else if (frontWheel1.steerAngle > 0) {
frontWheel1.steerAngle = frontWheel1.steerAngle - (steerSpeed * Time.deltaTime);
} else {
frontWheel1.steerAngle = frontWheel1.steerAngle + (steerSpeed * Time.deltaTime);
}
} else {
frontWheel1.steerAngle = frontWheel1.steerAngle + (steer * steerSpeed * Time.deltaTime);
if (frontWheel1.steerAngle > steer_max) { frontWheel1.steerAngle = steer_max; }
if (frontWheel1.steerAngle < -1 * steer_max) { frontWheel1.steerAngle = -1 * steer_max; }
}
frontWheel2.steerAngle = frontWheel1.steerAngle;
wheelFL.localEulerAngles.y = frontWheel1.steerAngle;
wheelFR.localEulerAngles.y = frontWheel2.steerAngle;

wheelFR.Rotate(0, 0, frontWheel1.rpm * -6 * Time.deltaTime);
wheelFL.Rotate(0, 0, frontWheel2.rpm * -6 * Time.deltaTime);
wheelMR.Rotate(0, 0, rearWheel1.rpm * -6 * Time.deltaTime);
wheelML.Rotate(0, 0, rearWheel2.rpm * -6 * Time.deltaTime);
wheelRR.Rotate(0, 0, rearWheel1.rpm * -6 * Time.deltaTime);
wheelRL.Rotate(0, 0, rearWheel2.rpm * -6 * Time.deltaTime);

}

What’s changed?

The truck tended to launch itself into space when going over jumps. Lots of fun but not very realistic. To address this I did two things.

First I scaled the truck down in size so it is about three meters long. In the first version it was over eleven meters long and nine meters tall – it was the size of a small two storey apartment. Using the correct scale is vitally important when using physics. The correct scale is 1:1 with the real world.

Second I increased the drag on the truck. This slows it down faster and makes it feel generally heavier.

I have added smoothing to the steering. Now when you turn left and right the wheels turn smoothly until they reach the maximum steering angle. When you release the steering controls the wheels rotate back to centered.

I changed the way the truck switches into and out of reverse. If you use the brake to stop the truck moving you have to release the brake key and then press it again to have the truck change into reverse (or forward) gear.

I got the middle set of wheels to rotate. I know I said I was not going to do that, but it bugged me that they did not move.

Finally I changed the wrap mode on the skybox textures from repeat to clamp. This got rid of the visible seams between the skybox textures. (Thanks to NickAVV on the forum for that one).

So what do you think? See anything else that could do with improving? If so let me know in the comments.