Tank physics?

I’m in the process of making a tank game. The current controls for my tank resemble a stone sliding on ice with rocket engines attached to it. I just use AddForce to move it and AddTorque to rotate it. I want to make it a little bit more realistic. I don’t want to use Translate or Rotate because I want it to work with physics.

Here’s what I was thinking: It should have high friction sideways and not slide much when turning on the move, be able to turn in place, accelerate and brake quite fast (same goes for turning), have enough power to push heavy objects but still move rather slow. Oh and it shouldn’t take off if its nose points up like it does now. Or keep moving if it’s upside down. I’m not looking for ultra-realism, just something that looks and feels good. I do have a quite nice damage model and beginnings of network game in place, but the movement needs work.

I’ve tried fiddling with wheel colliders, but haven’t come up with anything. I’m not even sure if they are the right way to go here. So if anyone has any tips or has made something similar, I’d like to hear.

Lol… everyone is working on games including tanks right now :slight_smile:

I’m working on the same topic and haven’t found any good solution to this. If I ever find a good solution, I’ll share it here :slight_smile:

Maybe a tank game seems easy at first :). But that’s not why I got into it, I’m trying to achieve a kind of arcade multiplayer tank simulator with physics and damage modeling similar to Men of War. Probably not WW2 however. I’m also thinking of adding helicopter-like aircraft, hover tanks, walkers etc. after I get the tanks working.

Well, I got something going, works pretty well so far. You can try it out here:
http://koti.mbnet.fi/marwer/tankcontrollertest.html
Wasd or arrow keys control the movement and mouse controls the camera. The turret has no functionality, this is just for driving around.

Here’s the code for anyone who’s intrested, comments are welcome:

// Variables for caching transform and rigidbody.
private var myTransform:Transform;
private var myRigidbody:Rigidbody;

//Variables for checking if the tank is on the ground and not upside down.
private var myGrounder;
private var grounded:boolean = false;

//The acceleration we want the tank to have when vertical input is given.
var acceleration:float = 10;
 
 //Variable for altering the friction force
 var frictionMultiplier:float = 2;

//The angular acceleration we want the tank to have when horizontal input is given.
var angularAcceleration:float = 10;

//Maximum turning speed.
var maxTurnSpeed = 1;

//Maximum speed.
var maxSpeed = 20;

//Angular "drag", acceleration in the opposite direction when tank is turning but input is not given.
var turnDrag:float = 10;

function Start(){
	//Cache transform and rigidbody and find the grounder component.
	myTransform = transform;
	myGrounder = myTransform.GetComponentInChildren(grounder);
	myRigidbody = rigidbody;
}

function Update () {
	//Find out if the tank is grounded.
	grounded = myGrounder.grounded;

	//Get inputs into variables.
	var hInput = Input.GetAxis("Horizontal");
	var vInput = Input.GetAxis("Vertical");
	
	//Variable for checking if tracks have power.
	var neutral:boolean = true;
	
	//The faster the tank moves, the more we want it to slide,
	var traction:float = 1 / myRigidbody.velocity.magnitude;
	
	//Local velocity is needed for calculating the friction force and limiting speed.
	var locVelocity = myTransform.InverseTransformDirection(myRigidbody.velocity);
	
	//The forward direction vector in world coordinates.
	var fwd = myTransform.TransformDirection(Vector3.forward);
	
	//The angle between our velocity vector and forward direction in world coordinates. Used for
	//checking if we are moving forward or in reverse. When the tank is still the angle is 90, 
	//we substract it just for clarity.
	var velocityAngle = Vector3.Angle(myRigidbody.velocity, fwd) - 90;
	
	//Apply force if the tank is grounded and not moving at maximum speed. Set neutral to false.
	if(vInput  grounded == true){
		neutral = false;
		if(locVelocity.z < maxSpeed  locVelocity.z > -maxSpeed){
			myRigidbody.AddForce(fwd * -vInput * acceleration * myRigidbody.mass);
		}
	}
	
	//Calculate friction force applied according to the difference between local velocity and forward direciton.
	//The more we are sliding sideways, the more friction force is applied. This is done to simulate the tracks
	// rolling freely when no power is applied to them.
	var frictionForce:float;
	var frictionAngle = Vector3.Angle(locVelocity, -Vector3.forward);
	if (frictionAngle < 90){
		frictionForce = frictionAngle;
	}
	else if (frictionAngle > 90){
		frictionForce = Mathf.Abs(frictionAngle - 180);
	}
	
	//Apply the friction force if we are grounded and moving.
	if (myRigidbody.velocity.magnitude >= 0.5  grounded == true){
			var d = -myRigidbody.velocity.normalized;
			myRigidbody.AddForce(d * frictionForce * frictionMultiplier);
		}
	
	//Apply torque accoriding to horizontal input when the tank is grounded and not turning at maximum speed. Also set neutral to false
	//because the tracks have power.
	if(hInput  grounded == true){
		neutral = false;
		if (rigidbody.angularVelocity.magnitude < maxTurnSpeed){ 
			myRigidbody.AddTorque(Vector3.up * hInput * angularAcceleration * myRigidbody.mass);
		}
	}else{
		//If no input is given we should stop turning quit quickly.
		myRigidbody.AddTorque(-myRigidbody.angularVelocity * turnDrag * myRigidbody.mass);
	}
	
	//Changing direction when turning on the move is simulated with Vector3.Slerp. The faster we are moving the less we should slerp in order
	//to simulate traction.
	if(velocityAngle > 0  neutral == false  grounded == true){
		myRigidbody.velocity = Vector3.Slerp(myRigidbody.velocity, -myTransform.forward * myRigidbody.velocity.magnitude, traction);
	}else if (velocityAngle < 0  neutral == false  grounded == true){
		myRigidbody.velocity = Vector3.Slerp(myRigidbody.velocity, myTransform.forward * myRigidbody.velocity.magnitude, traction);
	}
}

You will also need to add an empty gameobject as a child for your tank with a raycast collider working as a trigger and the following script. Make sure you call it grounder and the name of your terrain is “Terrain”. You could use tags or layers here too if you need to, but this is enough for me.

var grounded:boolean = false;

function OnTriggerEnter(other:Collider){
	if (other.name == "Terrain"){
		grounded = true;
	}
}

function OnTriggerExit(other:Collider){
	if (other.name == "Terrain"){
		grounded = false;
	}
}

I will still need to add animation for the tracks and control it in the script.

I first thought you were talking about getting the tracks to move. That is a forever topic here cause of the the track physics. There is a cool tank project in the showcase that works good. you may be able to expand on it and offer back a mutation of the two for an super tank controller. :smile:

Could you give me a link? I couldn’t find it. Though I was thinking of leaving the tracks static and just animate them.

That’s how I do it. At least you can animate them as you want when the tank is turning on place.

That said, I’m interested in the link, too :slight_smile:

Sorry guys, I cant find this again also. The demo was a working tank control where the turret moved good. But only theory on the tank treds talked up in the topic of replys. About linking the parts of the treds with fixed joints. i created one one time by importing the parts of the treds in seperate meshes then linking the tred parts together with joints and then scripting the wheels/tred turners. And incresing the friction on the wheels and treds to get grip. The only thing was the tred would loosen too much i could’nt get a tight enough fit. it looked kick ass, but i scraped it :frowning:

Maybe ill try to build another one. its lots of modeling though :idea: JUST TRICKY PLACEMENT

as a test i went from making a conveyer belt(static):
http://homepage.uab.edu/g3david/Unity/Conveyer.html
to making a rigidbody design,
ended up making a tank, modeled loosly after the scorpian in halo, here:
http://homepage.uab.edu/g3david/Unity/Tank.html
controls are mouse and up down left right, its not really good but it proves a concept
the conveyers work by doinga rigidbody.move command, and then at lateupdate, manually setting it back to its original position and updating teh texture offset to match the speed
same basic thing in tank except i use config joint to the same effect, flip it over and yull see it has inertia with it…its cool, but just some moving box colliders rigids

That looks pretty good David. The controls are a bit quirky but the movement of the tracks is cool. I had something similar in mind as what Black Mantis said, but as I said, I think I’ll leave the tracks static for now.

And I noticed that I should use FixedUpdate instead of Update for my tank controller. Issues arise with Update if fps drops, the controls start to lag.

Hello! I have created a package tank for Unity3D. It contains a 3D model of a Panzer III, the necessary scripts for motion and shot, and the wheels animation and sound. Also includes a view from inside the tank!
You can test it here: Buy Plugins & Code from CodeCanyon
This package is in Buy Plugins & Code from CodeCanyon

I hope you enjoy it =)

elritualk,

Does your package use wheel colliders or simply move the transform?

I purchased his tank package. It’s is very basic. Here is what I’ve found.

  1. The wheels do not have colliders. The track doesn’t move.
  2. The turret is turned with the arrow keys. The tank is turned with the AWDS keys. But the arrow keys also influence the movement of the tank confusing the total movement. For example, if I want to raise the turret, the tank speeds up. If I want to lower the turret, the tank goes backwards.
  3. The projectile is a simple white sphere. It bounces along the terrain when fired. It doesn’t explode.
  4. The tank has no decent texture.
  5. The model is not in FBX format. It’s in Maya format. But if you ask the developer for an FBX file, he’ll send you one.

Try Killer1390’s tank tutorial, entered in the UniKnowledge 2 competition. You can find it here. The scripts are really easy to understand, and written in Javascript. :slight_smile:

Doesn’t have animation, though, and has a very simple tank model. I used a different model, attached the scripts, and it worked like a dream. :smile:

Keys : WASD - turret, Arrows - movement, Spacebar - shoot.

Hope I’ve helped.

Your link does not work any more

of course it doesnt, its three years old.

check the dates of last post before you post in topics, or forever burn as a necro bumper