Yet Another Tank Driving Script

I’m a Unity noob, but I did search around for a tank control script, and didn’t find anything quite like what I needed. I tried using WheelColliders, but found that my tank pulled to the side even though I was careful to make sure my center of mass was right between the wheels.

So I gave up on that approach and tried instead applying forces directly. This has worked out really well, and I thought I’d share the script with the community.

var driveForce = 20000;
var turnTorque = 20000;
var antiskidForce = 10000;
var jumpForce = 2000000;
var forwardSpeed = 20;
var reverseSpeed = 15;
var turnRate = 5;

private var forwardSpeedGoal = 0.0;
private var turnSpeedGoal = 0.0;

function Start() {
	// Move the center of mass down for improved stability
	rigidbody.centerOfMass.y -= 1.0;
}

function Update () {
	var speed = Vector3.Dot(rigidbody.velocity, transform.forward);
		
	var vertInput = Input.GetAxis("Vertical");
	forwardSpeedGoal = vertInput * (vertInput > 0 ? forwardSpeed : reverseSpeed);
	
	turnSpeedGoal = Input.GetAxis("Horizontal") * turnRate;
	
	if (Input.GetButtonDown("Fire1")) {
		rigidbody.AddRelativeForce(Vector3.up * jumpForce);
	}
}

function FixedUpdate () {
	// control loop for forward speed
	var speed = Vector3.Dot(rigidbody.velocity, transform.forward);
	var error = forwardSpeedGoal - speed;
	rigidbody.AddRelativeForce(Vector3.forward * driveForce * error);

	// control loop to halt sideways slip
	var slip = Vector3.Dot(rigidbody.velocity, transform.right);
	error = -slip;
	rigidbody.AddRelativeForce(Vector3.right * antiskidForce * error);
	
	// control loop for turn rate
	var angVel = rigidbody.angularVelocity.y;
	error = turnSpeedGoal - angVel;
	rigidbody.AddRelativeTorque(Vector3.up * turnTorque * error);
}

In addition to simple driving, you can also press the Fire1 button to jump (I’m working on something like BZFlag, for those familiar with that).

This tank handles well, follows terrain nicely, etc., with only one problem: I don’t detect when the tank is in contact with the ground, so you can launch yourself into the air (by jumping or just driving real fast off a hill) and continue to drive and turn. Instead, you should just fall ballistically until your treads are on the ground again. (And ideally, how much traction you can get should depend on how much of the tread is in contact, and how much force is pressing them together, but that may be getting more complex than I really need.)

As a newbie, I’m not sure of the best way to add that feature. Should I put a collider on each tread? But how would I tell the difference between resting on the ground, and (say) something bumping into the tread from the side? Or should I cast a ray, as I understand WheelCollider does?

Thanks for any tips!

I believe the best idea would be to cast a ray.

OK, I’ll give that a try. Probably one ray from each end of each tread (i.e. four rays total) would suffice. Or if I want to get fancy, I could do three on each tread. That should let me adjust the traction of each tread according to how much is in contact with the ground — perhaps noticeable if you’re hanging partway off a ledge.

I’ll report back once I’ve had a chance to try it, and let y’all know how it went!

Thanks,

  • Joe

Joe – I am very interested in your results with the ray casting solution. I think the three rays on each tread would be best. I am also new to Unity and defer to someone with more experience with Unity.

I usually follow a more vehicle aproach to a tank. two tracks, 10 wheelColliders and power them without directly controlling the vehicle thorugh code.

The big part that I have found is that you have to do some calculation on the wheels. Press forward, and all 10 wheels roll forward, Moving forward, and press back, apply brakes to all 10 wheels until they reach below a certain speed, then start turning the backwards. (vice versa for going in reverse and pressing forward). Press Left or right while going below a certain speed, one side rotates forward, the other backward. Doing that while moving, apply brakes to one side or the other.

Past that it is a car. :wink:

Hi!
I’ve used your script in my game. It works perfectly for me. I havn’t found a similar one all over the internet, so thank you very much for this. Maybe I’ll place a link to my tank game here when I finish.
Keep up the good work! :smile: :smile: :smile: