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!