Created
December 26, 2017 08:50
-
-
Save mashanz/50c0b43724194c5e45bdb3f72f4b25eb to your computer and use it in GitHub Desktop.
UNITY CAR SCRIPT
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import System.IO.Ports; | |
import System.Threading; | |
private var wheelRadius : float = 0.4; | |
var suspensionRange : float = 0.1; | |
var suspensionDamper : float = 50; | |
var suspensionSpringFront : float = 18500; | |
var suspensionSpringRear : float = 9000; | |
public var brakeLights : Material; | |
var dragMultiplier : Vector3 = new Vector3(2, 5, 0.2); | |
var throttle : float = 0; | |
var steer : float = 0; | |
private var handbrake : boolean = false; | |
var centerOfMass : Transform; | |
var frontWheels : Transform[]; | |
var rearWheels : Transform[]; | |
private var wheels : Wheel[]; | |
wheels = new Wheel[frontWheels.Length + rearWheels.Length]; | |
private var wfc : WheelFrictionCurve; | |
var topSpeed : float = 74.5645; | |
var numberOfGears : int = 1; | |
var maximumTurn : int = 15; | |
var minimumTurn : int = 10; | |
public var Speedometer:int; | |
public var Speedmtr:float; | |
public var Timer :float; | |
public var star:Vector3; | |
public var last:Vector3; | |
public var Hitung:int=0; | |
public var AvarageSpeed:float; | |
var resetTime : float = 5.0; | |
private var resetTimer : float = 0.0; | |
private var engineForceValues : float[]; | |
private var gearSpeeds : float[]; | |
private var currentGear : int; | |
private var currentEnginePower : float = 0.0; | |
private var handbrakeXDragFactor : float = 0.1; | |
private var initialDragMultiplierX : float = 1.0; | |
private var handbrakeTime : float = 0.0; | |
private var handbrakeTimer : float = 1.0; | |
private var skidmarks : Skidmarks = null; | |
private var skidSmoke : ParticleEmitter = null; | |
var skidmarkTime : float[]; | |
private var sound : SoundController = null; | |
sound = transform.GetComponent(SoundController); | |
private var canSteer : boolean; | |
private var canDrive : boolean; | |
/************************************************************** | |
* Serial Output | |
**************************************************************/ | |
public static var sp : SerialPort ; | |
sp = new SerialPort(); | |
sp.BaudRate = 9600; | |
sp.PortName ="/dev/tty.SLAB_USBtoUART8"; | |
sp.Parity = Parity.None; | |
sp.DataBits = 8; | |
sp.StopBits = StopBits.One; | |
/************************************************************** | |
* Serial Input | |
**************************************************************/ | |
public static var sinput : SerialPort ; | |
sinput = new SerialPort(); | |
sinput.BaudRate = 9600; | |
sinput.PortName ="/dev/tty.SLAB_USBtoUART"; | |
sinput.Parity = Parity.None; | |
sinput.DataBits = 8; | |
sinput.StopBits = StopBits.One; | |
var count:int = 0; | |
var message: String; | |
var dataouput: String; | |
var datainput : String; | |
var data: int; | |
var parseString: String; | |
var parseStringOutput: String; | |
var Stir: int; | |
var shifter :String; | |
var gas: int; | |
var rem: int; | |
var arah: String; | |
var axis_x: int; | |
var axis_y: int; | |
var kirimdata :String; | |
var pengujian :String; | |
var outputpengujian:String; | |
var datakecepatan: String; | |
/************************************************************** | |
* MULTITHREAD | |
**************************************************************/ | |
var t1 = Thread(thread1); | |
var t2 = Thread(thread2); | |
var t3 = Thread(thread3); | |
//thread 1 menerima data dari input | |
function thread1(){ | |
while (true){ | |
sp.Open(); | |
if (sp.IsOpen ) { | |
datainput = sp.ReadLine(); | |
pengujian += datainput.ToString(); | |
shifter= datainput[10].ToString(); | |
arah = datainput[0].ToString(); | |
parseString = datainput[1].ToString()+datainput[2].ToString()+datainput[3].ToString(); | |
Stir=parseInt(parseString); | |
parseString = datainput[4].ToString()+datainput[5].ToString()+datainput[6].ToString(); | |
gas=parseInt(parseString); | |
parseString = datainput[7].ToString()+datainput[8].ToString()+datainput[9].ToString(); | |
rem=parseInt(parseString); | |
} | |
sp.Close(); | |
} | |
} | |
//thread 2 menerima data | |
function thread2(){ | |
while (true){ | |
sinput.Open(); | |
if (sinput.IsOpen ) { | |
sinput.Write("Coba"); | |
dataouput = sinput.ReadLine(); | |
outputpengujian+=dataouput.ToString(); | |
parseStringOutput = dataouput[0].ToString()+dataouput[1].ToString(); | |
axis_x=parseInt(parseStringOutput); | |
parseStringOutput = dataouput[2].ToString()+dataouput[3].ToString(); | |
axis_y=parseInt(parseStringOutput); | |
} | |
sinput.Close(); | |
} | |
} | |
//thread 3 mengirim data | |
function thread3(){ | |
while (true){ | |
sinput.Open(); | |
if (sinput.IsOpen ){ | |
if (Speedometer<10) datakecepatan="00"+Speedometer.ToString(); | |
if (Speedometer<100 && Speedometer >=10) datakecepatan="0"+Speedometer.ToString(); | |
if (Speedometer >=100) datakecepatan=Speedometer.ToString(); | |
kirimdata= arah+Stir.ToString()+datakecepatan+"\r\n"; | |
sinput.Write(kirimdata); | |
} | |
sinput.Close(); | |
} | |
} | |
/************************************************************** | |
* QUIT THE APP | |
**************************************************************/ | |
function OnApplicationQuit(){ | |
sp.Close(); | |
t1.Abort(); | |
t2.Abort(); | |
t3.Abort(); | |
} | |
/************************************************************** | |
* WHEEL PARAMETERS | |
**************************************************************/ | |
class Wheel { | |
var collider : WheelCollider; | |
var wheelGraphic : Transform; | |
var tireGraphic : Transform; | |
var driveWheel : boolean = false; | |
var steerWheel : boolean = false; | |
var lastSkidmark : int = -1; | |
var lastEmitPosition : Vector3 = Vector3.zero; | |
var lastEmitTime : float = Time.time; | |
var wheelVelo : Vector3 = Vector3.zero; | |
var groundSpeed : Vector3 = Vector3.zero; | |
} | |
/************************************************************** | |
* MAIN PROGRAM | |
**************************************************************/ | |
function Start() { | |
accelerationTimer = Time.time; | |
SetupWheelColliders(); | |
SetupCenterOfMass(); | |
SetupGears(); | |
SetUpSkidmarks(); | |
initialDragMultiplierX = dragMultiplier.x; | |
//t1.Start(); | |
//t2.Start(); | |
t3.Start(); | |
} | |
/************************************************************** | |
* PROGRAM UPDATER | |
**************************************************************/ | |
function Update(){ | |
var relativeVelocity : Vector3 = transform.InverseTransformDirection(rigidbody.velocity); | |
GetInput(); | |
Check_If_Car_Is_Flipped(); | |
UpdateWheelGraphics(relativeVelocity); | |
UpdateGear(relativeVelocity); | |
} | |
/************************************************************** | |
* FIXED UPDATE | |
**************************************************************/ | |
function FixedUpdate() { | |
// The rigidbody velocity is always given in world space, but in order to work in local space of the car model we need to transform it first. | |
var relativeVelocity : Vector3 = transform.InverseTransformDirection(rigidbody.velocity); | |
CalculateState(); | |
UpdateFriction(relativeVelocity); | |
UpdateDrag(relativeVelocity); | |
CalculateEnginePower(relativeVelocity); | |
ApplyThrottle(canDrive, relativeVelocity); | |
ApplySteering(canSteer, relativeVelocity); | |
Speedmtr =rigidbody.velocity.magnitude*3.6; | |
Speedometer= Mathf.Round(Speedmtr); | |
if(Timer==0){ | |
star=transform.position; | |
} | |
if(throttle>0){ | |
Timer += Time.deltaTime; | |
if (Timer>9 && Timer <10){ | |
last=transform.position; | |
AvarageSpeed=AvarageSpeed+Speedometer; | |
} else if (Timer<9 && Timer>0){ | |
AvarageSpeed=AvarageSpeed+Speedometer; | |
Hitung++; | |
} | |
} | |
//OpenConection(); | |
} | |
/************************************************************** | |
* Functions called from Start() | |
**************************************************************/ | |
function SetupWheelColliders(){ | |
SetupWheelFrictionCurve(); | |
var wheelCount : int = 0; | |
for (var t : Transform in frontWheels) { | |
wheels[wheelCount] = SetupWheel(t, true); | |
wheelCount++; | |
} | |
for (var t : Transform in rearWheels) { | |
wheels[wheelCount] = SetupWheel(t, false); | |
wheelCount++; | |
} | |
} | |
/************************************************************** | |
* SETUP | |
**************************************************************/ | |
function SetupWheelFrictionCurve() { | |
wfc = new WheelFrictionCurve(); | |
wfc.extremumSlip = 1; | |
wfc.extremumValue = 50; | |
wfc.asymptoteSlip = 2; | |
wfc.asymptoteValue = 25; | |
wfc.stiffness = 1; | |
} | |
/************************************************************** | |
* SETUP | |
**************************************************************/ | |
function SetupWheel(wheelTransform : Transform, isFrontWheel : boolean) { | |
var go : GameObject = new GameObject(wheelTransform.name + " Collider"); | |
go.transform.position = wheelTransform.position; | |
go.transform.parent = transform; | |
go.transform.rotation = wheelTransform.rotation; | |
var wc : WheelCollider = go.AddComponent(typeof(WheelCollider)) as WheelCollider; | |
wc.suspensionDistance = suspensionRange; | |
var js : JointSpring = wc.suspensionSpring; | |
if (isFrontWheel) js.spring = suspensionSpringFront; | |
else js.spring = suspensionSpringRear; | |
js.damper = suspensionDamper; | |
wc.suspensionSpring = js; | |
wheel = new Wheel(); | |
wheel.collider = wc; | |
wc.sidewaysFriction = wfc; | |
wheel.wheelGraphic = wheelTransform; | |
wheel.tireGraphic = wheelTransform.GetComponentsInChildren(Transform)[1]; | |
wheelRadius = wheel.tireGraphic.renderer.bounds.size.y / 2; | |
wheel.collider.radius = wheelRadius; | |
if (isFrontWheel) { | |
wheel.steerWheel = true; | |
go = new GameObject(wheelTransform.name + " Steer Column"); | |
go.transform.position = wheelTransform.position; | |
go.transform.rotation = wheelTransform.rotation; | |
go.transform.parent = transform; | |
wheelTransform.parent = go.transform; | |
} | |
else wheel.driveWheel = true; | |
return wheel; | |
} | |
/************************************************************** | |
* SETUP | |
**************************************************************/ | |
function SetupCenterOfMass() { | |
if(centerOfMass != null) rigidbody.centerOfMass = centerOfMass.localPosition; | |
} | |
/************************************************************** | |
* SETUP | |
**************************************************************/ | |
function SetupGears() { | |
engineForceValues = new float[numberOfGears]; | |
gearSpeeds = new float[numberOfGears]; | |
var tempTopSpeed : float = topSpeed; | |
for(var i = 0; i < numberOfGears; i++) { | |
if(i > 0) gearSpeeds[i] = tempTopSpeed + gearSpeeds[i-1]; | |
else gearSpeeds[i] = tempTopSpeed ; | |
tempTopSpeed -= tempTopSpeed ; | |
} | |
var engineFactor : float = topSpeed / gearSpeeds[gearSpeeds.Length - 1]; | |
for(i = 0; i < numberOfGears; i++) { | |
var maxLinearDrag : float = gearSpeeds[i] * gearSpeeds[i];// * dragMultiplier.z; | |
engineForceValues[i] = maxLinearDrag * engineFactor; | |
} | |
} | |
/************************************************************** | |
* SETUP | |
**************************************************************/ | |
function SetUpSkidmarks() { | |
if(FindObjectOfType(Skidmarks)) { | |
skidmarks = FindObjectOfType(Skidmarks); | |
skidSmoke = skidmarks.GetComponentInChildren(ParticleEmitter); | |
} | |
else Debug.Log("No skidmarks object found. Skidmarks will not be drawn"); | |
skidmarkTime = new float[4]; | |
for (var f : float in skidmarkTime) f = 0.0; | |
} | |
/************************************************************** | |
* Functions called from Update() | |
************************************************************** | |
* Setelah data ditrima | |
*/ | |
function GetInput() { | |
if (gas>0 && shifter =="D") { | |
throttle=1; | |
rigidbody.constraints= RigidbodyConstraints.None; | |
} | |
if (gas==0 && shifter == "D"){ | |
throttle= 0; | |
rigidbody.constraints= RigidbodyConstraints.None; | |
} | |
if (gas>0 && shifter =="R") { | |
throttle=-1; | |
rigidbody.constraints= RigidbodyConstraints.None; | |
} | |
if (gas==0 && shifter =="R") { | |
throttle=0; | |
Berhenti(); | |
} | |
if (shifter =="N") { | |
gas=0; | |
throttle=-1; | |
if (Speedometer<0.4){ | |
Berhenti(); | |
throttle=0; | |
} | |
} | |
if (shifter == "P"){ | |
throttle=0; | |
gas=0; | |
Berhenti(); | |
} | |
if (arah=="L"){ | |
steer= (-1)*Stir/450.0; | |
} | |
if (arah=="R"){ | |
steer= 1*Stir/450.0; | |
} | |
if(throttle < 0.0) brakeLights.SetFloat("_Intensity", Mathf.Abs(throttle)); | |
else brakeLights.SetFloat("_Intensity", 0.0); | |
CheckHandbrake(); | |
} | |
/************************************************************** | |
* JALAN | |
**************************************************************/ | |
function Jalan(){ | |
rigidbody.constraints= RigidbodyConstraints.None; | |
} | |
/************************************************************** | |
* STOP | |
**************************************************************/ | |
function Berhenti(){ | |
rigidbody.velocity= Vector3.zero; | |
rigidbody.angularVelocity=Vector3.zero; | |
rigidbody.constraints= RigidbodyConstraints.FreezePosition; | |
} | |
/************************************************************** | |
* CheckHandbrake() | |
**************************************************************/ | |
function CheckHandbrake() { | |
if(rem>10) { | |
throttle=-1; | |
if(!handbrake) { | |
handbrake = true; | |
handbrakeTime = Time.time; | |
dragMultiplier.x = initialDragMultiplierX * handbrakeXDragFactor; | |
} | |
currentEnginePower=rem; | |
if (Speedometer <1) Berhenti(); | |
} else if(handbrake) { | |
handbrake = false; | |
StartCoroutine(StopHandbraking(Mathf.Min(5, Time.time - handbrakeTime))); | |
Jalan(); | |
} | |
} | |
/************************************************************** | |
* StopHandbraking | |
**************************************************************/ | |
function StopHandbraking(seconds : float) { | |
var diff : float = initialDragMultiplierX - dragMultiplier.x; | |
handbrakeTimer = 1; | |
// Get the x value of the dragMultiplier back to its initial value in the specified time. | |
while(dragMultiplier.x < initialDragMultiplierX && !handbrake) { | |
dragMultiplier.x += diff * (Time.deltaTime / seconds); | |
handbrakeTimer -= Time.deltaTime / seconds; | |
yield; | |
} | |
dragMultiplier.x = initialDragMultiplierX; | |
handbrakeTimer = 0; | |
} | |
/************************************************************** | |
* CEK KALO MOBIL KEBALIK | |
**************************************************************/ | |
function Check_If_Car_Is_Flipped() { | |
if(transform.localEulerAngles.z > 80 && transform.localEulerAngles.z < 280) resetTimer += Time.deltaTime; | |
else resetTimer = 0; | |
if (resetTimer > resetTime) FlipCar(); | |
} | |
/************************************************************** | |
* MOBIL KEBALIK | |
**************************************************************/ | |
function FlipCar() { | |
transform.rotation = Quaternion.LookRotation(transform.forward); | |
transform.position += Vector3.up * 0.5; | |
rigidbody.velocity = Vector3.zero; | |
rigidbody.angularVelocity = Vector3.zero; | |
resetTimer = 0; | |
currentEnginePower = 0; | |
} | |
/************************************************************** | |
* UpdateWheelGraphics | |
**************************************************************/ | |
var wheelCount : float; | |
function UpdateWheelGraphics(relativeVelocity : Vector3) { | |
wheelCount = -1; | |
for(var w : Wheel in wheels) { | |
wheelCount++; | |
var wheel : WheelCollider = w.collider; | |
var wh : WheelHit = new WheelHit(); | |
// First we get the velocity at the point where the wheel meets the ground, if the wheel is touching the ground | |
if(wheel.GetGroundHit(wh)) { | |
w.wheelGraphic.localPosition = wheel.transform.up * (wheelRadius + wheel.transform.InverseTransformPoint(wh.point).y); | |
w.wheelVelo = rigidbody.GetPointVelocity(wh.point); | |
w.groundSpeed = w.wheelGraphic.InverseTransformDirection(w.wheelVelo); | |
// Code to handle skidmark drawing. Not covered in the tutorial | |
if(skidmarks) { | |
if(skidmarkTime[wheelCount] < 0.02 && w.lastSkidmark != -1) { | |
skidmarkTime[wheelCount] += Time.deltaTime; | |
} else { | |
var dt : float = skidmarkTime[wheelCount] == 0.0 ? Time.deltaTime : skidmarkTime[wheelCount]; | |
skidmarkTime[wheelCount] = 0.0; | |
var handbrakeSkidding : float = handbrake && w.driveWheel ? w.wheelVelo.magnitude * 0.3 : 0; | |
var skidGroundSpeed = Mathf.Abs(w.groundSpeed.x) - 15; | |
if(skidGroundSpeed > 0 || handbrakeSkidding > 0) { | |
var staticVel : Vector3 = transform.TransformDirection(skidSmoke.localVelocity) + skidSmoke.worldVelocity; | |
if(w.lastSkidmark != -1) { | |
var emission : float = UnityEngine.Random.Range(skidSmoke.minEmission, skidSmoke.maxEmission); | |
var lastParticleCount : float = w.lastEmitTime * emission; | |
var currentParticleCount : float = Time.time * emission; | |
var noOfParticles : int = Mathf.CeilToInt(currentParticleCount) - Mathf.CeilToInt(lastParticleCount); | |
var lastParticle : int = Mathf.CeilToInt(lastParticleCount); | |
for(var i = 0; i <= noOfParticles; i++) { | |
var particleTime : float = Mathf.InverseLerp(lastParticleCount, currentParticleCount, lastParticle + i); | |
skidSmoke.Emit( Vector3.Lerp(w.lastEmitPosition, wh.point, particleTime) + new Vector3(Random.Range(-0.1, 0.1), Random.Range(-0.1, 0.1), Random.Range(-0.1, 0.1)), staticVel + (w.wheelVelo * 0.05), Random.Range(skidSmoke.minSize, skidSmoke.maxSize) * Mathf.Clamp(skidGroundSpeed * 0.1,0.5,1), Random.Range(skidSmoke.minEnergy, skidSmoke.maxEnergy), Color.white); | |
} | |
} else { | |
skidSmoke.Emit( wh.point + new Vector3(Random.Range(-0.1, 0.1), Random.Range(-0.1, 0.1), Random.Range(-0.1, 0.1)), staticVel + (w.wheelVelo * 0.05), Random.Range(skidSmoke.minSize, skidSmoke.maxSize) * Mathf.Clamp(skidGroundSpeed * 0.1,0.5,1), Random.Range(skidSmoke.minEnergy, skidSmoke.maxEnergy), Color.white); | |
} | |
w.lastEmitPosition = wh.point; | |
w.lastEmitTime = Time.time; | |
w.lastSkidmark = skidmarks.AddSkidMark(wh.point + rigidbody.velocity * dt, wh.normal, (skidGroundSpeed * 0.1 + handbrakeSkidding) * Mathf.Clamp01(wh.force / wheel.suspensionSpring.spring), w.lastSkidmark); | |
sound.Skid(true, Mathf.Clamp01(skidGroundSpeed * 0.1)); | |
} else { | |
w.lastSkidmark = -1; | |
sound.Skid(false, 0); | |
} | |
} | |
} | |
} else { | |
// If the wheel is not touching the ground we set the position of the wheel graphics to | |
// the wheel's transform position + the range of the suspension. | |
w.wheelGraphic.position = wheel.transform.position + (-wheel.transform.up * suspensionRange); | |
if(w.steerWheel) w.wheelVelo *= 0.9; | |
else w.wheelVelo *= 0.9 * (1 - throttle); | |
if(skidmarks) { | |
w.lastSkidmark = -1; | |
sound.Skid(false, 0); | |
} | |
} | |
// If the wheel is a steer wheel we apply two rotations: | |
// *Rotation around the Steer Column (visualizes the steer direction) | |
// *Rotation that visualizes the speed | |
if(w.steerWheel) { | |
var ea : Vector3 = w.wheelGraphic.parent.localEulerAngles; | |
ea.y = steer * maximumTurn; | |
w.wheelGraphic.parent.localEulerAngles = ea; | |
w.tireGraphic.Rotate(Vector3.right * (w.groundSpeed.z / wheelRadius) * Time.deltaTime * Mathf.Rad2Deg); | |
} else if(!handbrake && w.driveWheel) { | |
// If the wheel is a drive wheel it only gets the rotation that visualizes speed. | |
// If we are hand braking we don't rotate it. | |
w.tireGraphic.Rotate(Vector3.right * (w.groundSpeed.z / wheelRadius) * Time.deltaTime * Mathf.Rad2Deg); | |
} | |
} | |
} | |
/************************************************************** | |
* UpdateGear | |
**************************************************************/ | |
function UpdateGear(relativeVelocity : Vector3) { | |
currentGear = 0; | |
for(var i = 0; i < numberOfGears - 1; i++) { | |
if(relativeVelocity.z > gearSpeeds[i]) currentGear = i + 1; | |
} | |
} | |
/************************************************************** | |
* Functions called from FixedUpdate() | |
**************************************************************/ | |
function UpdateDrag(relativeVelocity : Vector3) { | |
var relativeDrag : Vector3 = new Vector3( -relativeVelocity.x * Mathf.Abs(relativeVelocity.x), | |
-relativeVelocity.y * Mathf.Abs(relativeVelocity.y), | |
-relativeVelocity.z * Mathf.Abs(relativeVelocity.z) ); | |
var drag = Vector3.Scale(dragMultiplier, relativeDrag); | |
if(initialDragMultiplierX > dragMultiplier.x) { // Handbrake code | |
drag.x /= (relativeVelocity.magnitude / (topSpeed / ( 1 + 2 * handbrakeXDragFactor ) ) ); | |
drag.z *= (1 + Mathf.Abs(Vector3.Dot(rigidbody.velocity.normalized, transform.forward))); | |
drag += rigidbody.velocity * Mathf.Clamp01(rigidbody.velocity.magnitude / topSpeed); | |
} else { // No handbrake | |
drag.x *= topSpeed / relativeVelocity.magnitude; | |
} | |
if(Mathf.Abs(relativeVelocity.x) < 5 && !handbrake) drag.x = -relativeVelocity.x * dragMultiplier.x; | |
rigidbody.AddForce(transform.TransformDirection(drag) * rigidbody.mass * Time.deltaTime); | |
} | |
/************************************************************** | |
* UpdateFriction | |
**************************************************************/ | |
function UpdateFriction(relativeVelocity : Vector3) { | |
var sqrVel : float = relativeVelocity.x * relativeVelocity.x; | |
// Add extra sideways friction based on the car's turning velocity to avoid slipping | |
wfc.extremumValue = Mathf.Clamp(300 - sqrVel, 0, 300); | |
wfc.asymptoteValue = Mathf.Clamp(150 - (sqrVel / 2), 0, 150); | |
for(var w : Wheel in wheels) { | |
w.collider.sidewaysFriction = wfc; | |
w.collider.forwardFriction = wfc; | |
} | |
} | |
/************************************************************** | |
* CalculateEnginePower | |
**************************************************************/ | |
function CalculateEnginePower(relativeVelocity : Vector3) { | |
if(throttle == 0) { | |
currentEnginePower=0; //-= Time.deltaTime * 200; | |
} else if( HaveTheSameSign(relativeVelocity.z, throttle) ) { | |
//normPower = (currentEnginePower / engineForceValues[engineForceValues.Length - 1]) * 2; | |
currentEnginePower= gas; //+= Time.deltaTime * 200 * EvaluateNormPower(normPower); | |
} else { | |
currentEnginePower -= Time.deltaTime * 300; | |
} | |
if(currentGear == 0) currentEnginePower = Mathf.Clamp(currentEnginePower, 0, engineForceValues[0]); | |
else currentEnginePower = Mathf.Clamp(currentEnginePower, engineForceValues[currentGear - 1], engineForceValues[currentGear]); | |
} | |
/************************************************************** | |
* CalculateState() | |
**************************************************************/ | |
function CalculateState() { | |
canDrive = false; | |
canSteer = false; | |
for(var w : Wheel in wheels) { | |
if(w.collider.isGrounded) { | |
if(w.steerWheel) canSteer = true; | |
if(w.driveWheel) canDrive = true; | |
} | |
} | |
} | |
/************************************************************** | |
* ApplyThrottle | |
**************************************************************/ | |
function ApplyThrottle(canDrive : boolean, relativeVelocity : Vector3) { | |
if(canDrive) { | |
var throttleForce : float = 0; | |
var brakeForce : float = 0; | |
if (HaveTheSameSign(relativeVelocity.z, throttle)) { | |
if (!handbrake) throttleForce = Mathf.Sign(throttle) * currentEnginePower * rigidbody.mass; | |
} else brakeForce = Mathf.Sign(throttle) * engineForceValues[0] * rigidbody.mass; | |
rigidbody.AddForce(transform.forward * Time.deltaTime * (throttleForce + brakeForce)); | |
} | |
} | |
/************************************************************** | |
* ApplySteering | |
**************************************************************/ | |
function ApplySteering(canSteer : boolean, relativeVelocity : Vector3) { | |
if(canSteer) { | |
var turnRadius : float = 3.0 / Mathf.Sin((90 - (steer * 30)) * Mathf.Deg2Rad); | |
var minMaxTurn : float = EvaluateSpeedToTurn(rigidbody.velocity.magnitude); | |
var turnSpeed : float = Mathf.Clamp(relativeVelocity.z / turnRadius, -minMaxTurn / 10, minMaxTurn / 10); | |
transform.RotateAround( transform.position + transform.right * turnRadius * steer, | |
transform.up, | |
turnSpeed * Mathf.Rad2Deg * Time.deltaTime * steer); | |
var debugStartPoint = transform.position + transform.right * turnRadius * steer; | |
var debugEndPoint = debugStartPoint + Vector3.up * 5; | |
Debug.DrawLine(debugStartPoint, debugEndPoint, Color.red); | |
if(initialDragMultiplierX > dragMultiplier.x) { // Handbrake | |
// rotationDirection is -1 or 1 by default, depending on steering | |
var rotationDirection : float = Mathf.Sign(steer); | |
if(steer == 0) { | |
// If we are not steering and we are handbraking and not rotating fast, we apply a random rotationDirection | |
if(rigidbody.angularVelocity.y < 1) rotationDirection = Random.Range(-1.0, 1.0); | |
else rotationDirection = rigidbody.angularVelocity.y; // If we are rotating fast we are applying that rotation to the car | |
} | |
// -- Finally we apply this rotation around a point between the cars front wheels. | |
transform.RotateAround( transform.TransformPoint( ( frontWheels[0].localPosition + frontWheels[1].localPosition) * 0.5), | |
transform.up, | |
rigidbody.velocity.magnitude * Mathf.Clamp01(1 - rigidbody.velocity.magnitude / topSpeed) * rotationDirection * Time.deltaTime * 2); | |
} | |
} | |
} | |
/************************************************** | |
* Utility Functions * | |
**************************************************/ | |
function Convert_Miles_Per_Hour_To_Meters_Per_Second(value : float) : float { | |
return value * 0.44704; | |
} | |
function Convert_Meters_Per_Second_To_Miles_Per_Hour(value : float) : float { | |
return value * 2.23693629; | |
} | |
function HaveTheSameSign(first : float, second : float) : boolean { | |
if (Mathf.Sign(first) == Mathf.Sign(second)) return true; | |
else return false; | |
} | |
function EvaluateSpeedToTurn(speed : float) { | |
if(speed > topSpeed / 2) return minimumTurn; | |
var speedIndex : float = 1 - (speed / (topSpeed / 2)); | |
return minimumTurn + speedIndex * (maximumTurn - minimumTurn); | |
} | |
function EvaluateNormPower(normPower : float) { | |
if(normPower < 1) return 10 - normPower * 9; | |
else return 1.9 - normPower * 0.9; | |
} | |
function GetGearState() { | |
var relativeVelocity : Vector3 = transform.InverseTransformDirection(rigidbody.velocity); | |
var lowLimit : float = (currentGear == 0 ? 0 : gearSpeeds[currentGear-1]); | |
return (relativeVelocity.z - lowLimit) / (gearSpeeds[currentGear - lowLimit]) * (1 - currentGear * 0.1) + currentGear * 0.1; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment