A little help for making a semi-realistic motorbike physics

Hi,

I’m trying to build a motorbike game ala Bike Barron or Motoheroz. I’ve build a somewhat working game, but the physics is not exactly sufficient. These are what I’ve made so far:

  1. The bike consists of the body, forks / suspensions (front and rear), wheels (front and rear), and a rider / character.
  2. The rigidbody of all objects are constrained like this:
    – freeze position: x
    – freeze rotation: y, z
    Meaning: It can move along the y z plane and rotate only by its x axis
  3. The wheels are attached to their corresponding forks by joints, likewise with the forks and the body.
  4. The joints linking the wheels and forks are configurable joints with locked x,y,z motion and locked x y angular motion, and a free z angular motion (so that it can rotate to move the bike)
  5. The joints linking the forks and body are also configurable with a limited y motion and locked all other motions, and also some spring and damper to simulate suspensions.
  6. The character / rider is attached on a node, has ragdoll that is configured with isKinematic turned on.
  7. The wheels are using SphereColliders that are rotated with a torque and give an acceleration to it as in real life situation.
  8. The wheels are using a physics material with both dynamic and static friction to 1 so to avoid skidding /slipping, and will generate the needed traction to move the bike.
  9. The rigidbodies have the standart default drag values of 0 and 0.05 for linear and angular drag.

This is my MotorcycleController.cs file:

using UnityEngine;
using System.Collections;

public class MotorcycleController : MonoBehaviour
{
	//The enum for the wheeldrive type
	public enum eWheelDriveType	
	{
		NONE,
		REAR_WD,
		FRONT_WD,
		FOUR_WD
	}
	
	
	//The bike itself.
	//Consisted of: the body frame, forks / suspensions, and wheels. All of these components will be attached via joints.
	public Rigidbody body;
	public Transform frontFork;
	public Transform frontWheel;
	public Transform rearFork;
	public Transform rearWheel;
	
	private GroundDetection rearWheelGroundDetect;
	private GroundDetection frontWheelGroundDetect;
	
	public eWheelDriveType wheelDriveType = eWheelDriveType.REAR_WD;
	public float maxWheelAngularVelocity = 120.0f;
	public float torque = 200.0f;
	public float reverseTorque = 80.0f;
	public float onGroundRotationTorque = 500.0f;
	public float inAirRotationTorque = 700.0f;
	
	//Center of mass of the bike.
	public Transform centerOfMass;
	
	//Character / rider attachment node
	public Transform characterAttachPosition;
	//-------------------------------------------
			
	//Flag to determine whether we are in the air or not
	private bool isInAir = false;		
	
	//Engine sound
	private AudioSource engineSound;
 	private float pitch;
	
	
	//Game inputs	
	private bool accelerate = false;
	private bool reverse = false;	
	private bool left = false;
	private bool right = false;		
	
	void Awake ()
	{

	}
	
	void Start ()
	{
		
		//Ignoring collisions
		Physics.IgnoreCollision (frontWheel.collider, body.collider);
		Physics.IgnoreCollision (rearWheel.collider, body.collider);
		
		Physics.IgnoreLayerCollision(LayerMask.NameToLayer("Bike"), LayerMask.NameToLayer ("Bike"),true);
		Physics.IgnoreLayerCollision(LayerMask.NameToLayer("Bike"), LayerMask.NameToLayer ("Character"),true);
		Physics.IgnoreLayerCollision(LayerMask.NameToLayer("Bike"), LayerMask.NameToLayer ("CharacterCollider"),true);
		
		//Audio source for the engine sound. Its pitch be changed according to the current angular velocity
		engineSound = body.GetComponent<AudioSource>();		
		
		//setting rear wheel max angular rotation speed
		//rearWheel.GetComponent<Rigidbody> ().maxAngularVelocity = speed;	
		
		if (wheelDriveType == eWheelDriveType.REAR_WD || wheelDriveType == eWheelDriveType.FOUR_WD)
		{
			rearWheel.GetComponent<Rigidbody> ().maxAngularVelocity = maxWheelAngularVelocity;
		}
		
		if (wheelDriveType == eWheelDriveType.FRONT_WD || wheelDriveType == eWheelDriveType.FOUR_WD)
		{
			frontWheel.GetComponent<Rigidbody> ().maxAngularVelocity = maxWheelAngularVelocity;
		}
		
		frontWheelGroundDetect = frontWheel.GetComponent<GroundDetection>(); //Detect wheelie
		rearWheelGroundDetect = rearWheel.GetComponent<GroundDetection>(); //Detect wheelie
		
		frontWheelGroundDetect.Create(body.gameObject);
		rearWheelGroundDetect.Create(body.gameObject);
		
		body.rigidbody.centerOfMass = centerOfMass.localPosition;		
	}
	
	void Update()
	{
		if ( GameManager.instance.GetGamePlayerManager().LifeStatus() == GamePlayerManager.eLifeStatus.ALIVE 
					 GameInput.instance.isInputActive)
		{
				
			//GameInput is a singleton that will handle all inputs according to the platform and mode.
			if(GameInput.instance.RightLeft > 0)
				right = true;
			else
				right = false;
			
			if(GameInput.instance.RightLeft < 0)
				left = true;
			else 
				left = false;
				
			if(GameInput.instance.ForwardBackward > 0)
				accelerate = true;
			else
				accelerate = false;				
				
			if(GameInput.instance.ForwardBackward < 0)
				reverse = true;
			else
				reverse = false;				
				//----------------------------------
		
			
			//Changing engine sound pitch depending on the wheel drive's (or the rear for 4WD) angular velocity
			if(accelerate || reverse) 
			{
				Rigidbody wheelRigidbody;
				if (wheelDriveType == eWheelDriveType.FRONT_WD)
					wheelRigidbody = frontWheel.rigidbody;
				else
					wheelRigidbody = rearWheel.rigidbody;
				
				pitch = wheelRigidbody.angularVelocity.sqrMagnitude / maxWheelAngularVelocity;
				pitch *= Time.deltaTime * 2;
				pitch = Mathf.Clamp (pitch + 1, 0.5f,2.0f);			
			}
			else
				pitch = Mathf.Clamp (pitch - Time.deltaTime * 2, 0.5f, 2.0f);																
		}		


		
		//Clamping again. I'm paranoid. :P
		pitch = Mathf.Clamp (pitch - Time.deltaTime * 2, 0.5f, 1.8f);
		engineSound.pitch = pitch;
		
	}
	

	void FixedUpdate ()
	{			
		if ( GameManager.instance.GetGamePlayerManager().LifeStatus() == GamePlayerManager.eLifeStatus.ALIVE 
					 GameInput.instance.isInputActive)
		{		
			if (accelerate)
			{
				if (wheelDriveType == eWheelDriveType.REAR_WD || wheelDriveType == eWheelDriveType.FOUR_WD)
				{
					rearWheel.rigidbody.AddTorque (Vector3.right * torque * Time.deltaTime ,ForceMode.Impulse);	//add rotational speed to rear wheel
				}
				
				if (wheelDriveType == eWheelDriveType.FRONT_WD || wheelDriveType == eWheelDriveType.FOUR_WD)
				{
					frontWheel.rigidbody.AddTorque (Vector3.right * torque * Time.deltaTime ,ForceMode.Impulse);	//add rotational speed to front wheel
				}
				
				
			} //else dirt.Stop ();
			else if(reverse)
			{
				if (wheelDriveType == eWheelDriveType.REAR_WD || wheelDriveType == eWheelDriveType.FOUR_WD)
				{
					rearWheel.rigidbody.AddTorque (new Vector3 (-reverseTorque * Time.deltaTime, 0.0f, 0.0f),ForceMode.Impulse);	//add rotational speed to rear wheel
				}
					
				if (wheelDriveType == eWheelDriveType.FRONT_WD || wheelDriveType == eWheelDriveType.FOUR_WD)
				{
					frontWheel.rigidbody.AddTorque (new Vector3 (-reverseTorque * Time.deltaTime, 0.0f, 0.0f),ForceMode.Impulse);	//add rotational speed to front wheel
				}

			}

	        	
			if (left) 
			{ 
				if (!isInAir) 
				{ 
					body.AddTorque (new Vector3 (-onGroundRotationTorque * Time.deltaTime, 0.0f, 0.0f )); 
				} 
				else 
				{
					body.AddTorque (new Vector3 (-inAirRotationTorque * Time.deltaTime, 0.0f, 0.0f));    
				}
	
			} 
			else if (right) 
			{ 
				if (!isInAir) 
				{ 
					body.AddTorque (new Vector3 (onGroundRotationTorque * Time.deltaTime, 0.0f, 0.0f));				
				} 
				else 
				{
					body.AddTorque (new Vector3 (inAirRotationTorque * Time.deltaTime, 0, 0));   
				}
	
			}
					
			if(rearWheelGroundDetect.IsOnTerrain) //Check for ground
			{		
				isInAir = false;									
			}
			else 
			{
				isInAir = true;
			}
			
		}
	}
}

So, the problems I have right now are:

  1. The bike accelerates so slowly, even with a very big torque and a very big max angular velocity like 1000000. I know it’s probably because of the physics material settings of the wheels, but even when I changed it into a smaller value (like 0.6 or 0.4) it didn’t change a lot. And a value of 0.2 or less even gave me worse result as the wheels are slipping and couldn’t generate any movement force.
  2. If the bike jumps in the air, the wheel rotates faster. And when it lands, the bike runs faster like on a boost or nitro or something. Again, quite probably because of the drag values and combined with the maxAngularVelocity value. Can anybody give me a somewhat correct formula to determine a wheel’s max rotation speed based on its torque?
  3. The levels of my game often have a combination of small platforms, each with its own box colliders. I used copies of the same prefab of the objects for this. And I don’t know why but the torque wasn’t applied correctly to my drive wheel because of these platforms. It’s as if you throttled / de-throttled the gas every time the wheels hit a collider.
  4. If I release the throttle / acceleration, the bike won’t slow down and came to a halt. I know that it’s probably because of the drags of the rigidbodies, but I assumed that the deceleration from the wheel’s frictions will be sufficient for this. And also, I was afraid that defining drag values will make the bike accelerate even slower.
  5. I plan to use a wheelie / balancing with only one wheel for bonus points. But I have no idea about how to do this. Can you guys help me with this?

Can you guys help me here? I’m stuck. Thanks a lot in advance.

EDIT: I just realized that the title is not exactly correct. It should’ve been “A little help needed for…” How do you edit the title?

Anyone? bump

NECRO BUMP ALERT:

If you still need help bro, i can give you a hand. I simply steered clear of wheel colliders and used a velocity-based physics model instead. Here is a web demo:
[Bike Physics Example](https://googledrive.com/host/0B2tqYgzg1_lWWTVLa21ERkQ5R0U/Bike example.html)
And here is my code. Note that this requires that your bike has colliders on the wheels and bike body ONLY. the script also has some particle code commented out, but feel free to use it if your motorbike has particles for exhausts, skiddies, etc:

#pragma strict

//engine
var speed : float;
private var accel : float;
@range(0,10)
var acceleration : float;
//var exhaustSystem : ParticleSystem;
//var exhaustSystem2 : ParticleSystem;
//var Smoke : ParticleSystem;
//control
var brakePower : float;
var steer : float;
var FrontWheel : GameObject;
var BackWheel : GameObject;

function Start () {
	rigidbody.centerOfMass.y = 0.25;
//	Smoke.Stop();
}

function FixedUpdate () {
	var movement : Vector3;
	movement = transform.TransformDirection(Vector3.forward) * Mathf.Lerp(0,speed,accel);
	movement.y = rigidbody.velocity.y;
	if (Input.GetButton("Gas")) {
		accel += acceleration/100;
		if (accel >= 1){
		accel = 1;
		}
		rigidbody.velocity = movement;
//		exhaustSystem.Play();
//		exhaustSystem2.Play();
	}
	else {
		accel = 0;
//		exhaustSystem.Stop();
//		exhaustSystem2.Stop();
	}
	
	if (Input.GetButton("Brake")) {
		rigidbody.drag = brakePower;
	}
	else {
		rigidbody.drag = 0;
	}
	
	var spinSpeed : int = rigidbody.velocity.magnitude;
	if (spinSpeed <= 0.001){
		spinSpeed = 0;
	}
	
	//controls
	if (Physics.Raycast(FrontWheel.transform.position,-Vector3.up,1.5)){
		FrontWheel.transform.Rotate(0,-spinSpeed,0);
	}
	if (Input.GetButton("Gas")){
		BackWheel.transform.Rotate(0,Mathf.Lerp(-acceleration*20,-spinSpeed,accel),0);
	}
	else {
		BackWheel.transform.Rotate(0,-spinSpeed,0);
	}
	
	transform.rotation.eulerAngles.z = -Input.GetAxis("X") * 12;
	if (Input.GetAxis("X")  rigidbody.velocity.magnitude > speed/100){
		transform.Rotate(transform.up  * Input.GetAxis("X") * steer);
	}
//	if (Input.GetButton("Gas")  rigidbody.velocity.magnitude < speed / 4  acceleration >= 1){
//		Smoke.Emit(acceleration*10);
//	}	
}

Note that this bike, although it aims to be realistic, is more of an arcade bike than a realism bike. and this doesn’t quite work wioth slopes yet…

Hi,I am buliding a motorBike Project. The Physics I use is the same as you. the front connect with body using ConfigurationJoint and allow the Y move motion. the rear connect whit body using hingeJoint.
.But I have a problem. see the picture. When the bike run into the collider with high speed. The body stops,but the wheel move because of its speed. After a while , the wheel resume normal position . Even I use joint ,but the move power is very big ,then rigidbody could move out of my bounds.
What can I do?

1701311--106897--QQ截图20140717160515.png