private void CreateSkidmark() { GameObject goSkid = new GameObject("Skid"); FlatLineRenderer FLR = goSkid.AddComponent <FlatLineRenderer>(); Material Mat = (Material)Resources.Load("Prefabs/Materials/SkidMark"); FLR.Init(); FLR.SetMaterial(Mat); FLR.Width = 1; FLR.AddNode(new Vector3(-20, 10, 0)); FLR.AddNode(new Vector3(-30, 10, 0)); FLR.AddNode(new Vector3(-40, 10, 0)); FLR.AddNode(new Vector3(-50, 10, 0)); FLR.AddNode(new Vector3(-60, 10, 0)); }
// Update is called once per frame //FixedUpdate is called for every physics calculation void FixedUpdate() { GetInputFromInputManager(); //The rest of this method controls the car WCFL.brakeTorque = BrakeForce; WCFR.brakeTorque = BrakeForce; WCRL.brakeTorque = BrakeForce; WCRR.brakeTorque = BrakeForce; WCRL.motorTorque = v; WCRR.motorTorque = v; if (WCRL.rpm < -300) { WCRL.motorTorque = Mathf.Clamp(WCRL.motorTorque, 0, 10000); WCRR.motorTorque = Mathf.Clamp(WCRR.motorTorque, 0, 10000); } if (_rimSpin) { if (Mathf.Abs(WCFL.rpm) > 300) { _fLRimSpinRenderer.enabled = true; _fLRimRenderer.enabled = false; } else { _fLRimRenderer.enabled = true; _fLRimSpinRenderer.enabled = false; } if (Mathf.Abs(WCRL.rpm) > 300) { _rLRimSpinRenderer.enabled = true; _rLRimRenderer.enabled = false; } else { _rLRimRenderer.enabled = true; _rLRimSpinRenderer.enabled = false; } if (Mathf.Abs(WCFR.rpm) > 300) { _fRRimRenderer.enabled = false; _fRRimSpinRenderer.enabled = true; } else { _fRRimRenderer.enabled = true; _fRRimSpinRenderer.enabled = false; } if (Mathf.Abs(WCRR.rpm) > 300) { _rRRimRenderer.enabled = false; _rRRimSpinRenderer.enabled = true; } else { _rRRimRenderer.enabled = true; _rRRimSpinRenderer.enabled = false; } } //Adapt the tyre slip according to the road type bool GravelSimulation = false; if (Gps != null) { UnityEngine.Profiling.Profiler.BeginSample("AdaptSlip"); RoadMat = Gps.RoadMat; switch (RoadMat) { case "Tarmac": case "Washboard": frontFrict = frontFrictTarmac; rearFrict = rearFrictTarmac; break; case "DirtyRoad": frontFrict = frontFrictDirtyRoad; rearFrict = rearFrictDirtyRoad; //GravelSimulation = true; break; default: frontFrict = frontFrictDirt; rearFrict = rearFrictDirt; GravelSimulation = true; break; } SkidThresh = rearFrict.keys[1].time; UnityEngine.Profiling.Profiler.EndSample(); UnityEngine.Profiling.Profiler.BeginSample("ReverseSteer"); //For Rear wheel drive we give a little extra torque when reverse steering in a skid Vector3 _vel = _rb.velocity; float _rearSlideSlip = Vector3.Angle(_vel, transform.forward); if (WCRL.angularVelocity > 0) { //Easy cornering - The GPS can manage the reverse steering float BendAnglePerSec = 0; UnityEngine.Profiling.Profiler.BeginSample("CalcNewF"); if (Gps.CurrBend != null) { BendAnglePerSec = Gps.CurrBend.AnglePerSeg * Gps.SegsPerSec; float CorrectionAnglePerSec = (BendAnglePerSec - _rb.angularVelocity.y * 57.3f); if (Mathf.Sign(CorrectionAnglePerSec) != Mathf.Sign(BendAnglePerSec)) //only apply the correction if oversteering { h += CorrectionAnglePerSec; } h = Mathf.Clamp(h, -40, 40); } WCRL.fFriction.forceCoefficient = FCoef; WCRR.fFriction.forceCoefficient = FCoef; WCRL.sideFriction.forceCoefficient = SCoef; WCRR.sideFriction.forceCoefficient = SCoef; Vector3 cross = Vector3.Cross(_vel, transform.forward); if (Mathf.Abs(h) < 3 || Mathf.Sign(cross.y) != Mathf.Sign(h)) { WCRL.motorTorque *= (1 + Mathf.Abs(_rearSlideSlip) / 90f); WCRR.motorTorque *= (1 + Mathf.Abs(_rearSlideSlip) / 90f); WCRL.fFriction.forceCoefficient *= (1 + Mathf.Abs(_rearSlideSlip) / 90f); WCRR.fFriction.forceCoefficient *= (1 + Mathf.Abs(_rearSlideSlip) / 90f); } } //going forwrds //spinout //if (_rearSlideSlip > 90) { WCRL.sFriction.forceCoefficient = 0.2f; WCRR.sFriction.forceCoefficient = 0.2f; } } else //if gps is null { frontFrict = frontFrictDirt; rearFrict = rearFrictDirt; RoadMat = "Dirt"; } if (frontFrict == frontFrictTarmac && _rb.velocity.sqrMagnitude > 4) { h = h / 2; } WCFL.steerAngle = h; WCFR.steerAngle = h; //comment out this block for roadmat testing WCFL.forwardFriction.frictionCurve = frontFrict; WCFR.forwardFriction.frictionCurve = frontFrict; WCRL.forwardFriction.frictionCurve = rearFrict; WCRR.forwardFriction.frictionCurve = rearFrict; WCFL.GravelSimulation = GravelSimulation; WCFR.GravelSimulation = GravelSimulation; WCRL.GravelSimulation = GravelSimulation; WCRR.GravelSimulation = GravelSimulation; #region Anti-Roll bar Region float travelL; float travelR; float AntiRoll = AntiRollForce * GetComponent <Rigidbody>().velocity.magnitude; bool groundedFL = WCFL.GetGroundHit(out hitFL); //float ContactAngle; //WheelFrictionCurve Fric; //Fric = WCFL.forwardFriction; if (groundedFL) { travelL = 1 - WCFL.springCompression; // (-WCFL.transform.InverseTransformPoint(hitFL.point).y - WCFL.radius) / WCFL.springLength; } else { travelL = 1.0f; } bool groundedFR = WCFR.GetGroundHit(out hitFR); if (groundedFR) { travelR = 1 - WCFR.springCompression; // (-WCFR.transform.InverseTransformPoint(hitFR.point).y - WCFR.radius) / WCFR.springLength; } else { travelR = 1.0f; } var antiRollForce = (travelL - travelR) * AntiRoll; if (groundedFL) { GetComponent <Rigidbody>().AddForceAtPosition(WCFL.transform.up * antiRollForce, WCFR.transform.position); GetComponent <Rigidbody>().AddForceAtPosition(WCFL.transform.up * -antiRollForce, WCFL.transform.position); } if (groundedFR) { GetComponent <Rigidbody>().AddForceAtPosition(WCFR.transform.up * -antiRollForce, WCFL.transform.position); GetComponent <Rigidbody>().AddForceAtPosition(WCFR.transform.up * antiRollForce, WCFR.transform.position); } //BACK WHEEL ANTI-ROLL BAR bool groundedRL = WCRL.GetGroundHit(out hitRL); bool groundedRR = WCRR.GetGroundHit(out hitRR); float ForwardSlipRL = hitRL.forwardSlip; if (groundedRL) { travelL = (-WCRL.transform.InverseTransformPoint(hitRL.point).y - WCRL.radius) / WCRL.springLength; } else { travelL = 1.0f; } if (WCRL.SlipVectorMagnitude > SkidThresh * 2.25f && RoadMat == "Tarmac") { IsSkiddingRL = true; } else { IsSkiddingRL = false; } float ForwardSlipRR = hitRR.forwardSlip; if (groundedRR) { travelR = (-WCRR.transform.InverseTransformPoint(hitRR.point).y - WCRR.radius) / WCRR.springLength; } else { travelR = 1.0f; } if (WCRR.SlipVectorMagnitude > SkidThresh * 2.25f && RoadMat == "Tarmac") { IsSkiddingRR = true; } else { IsSkiddingRR = false; } antiRollForce = (travelL - travelR) * AntiRoll; if (groundedRL) { GetComponent <Rigidbody>().AddForceAtPosition(WCRL.transform.up * antiRollForce, WCRR.transform.position); GetComponent <Rigidbody>().AddForceAtPosition(WCRL.transform.up * -antiRollForce, WCRL.transform.position); } if (groundedRR) { GetComponent <Rigidbody>().AddForceAtPosition(WCRR.transform.up * -antiRollForce, WCRL.transform.position); GetComponent <Rigidbody>().AddForceAtPosition(WCRR.transform.up * antiRollForce, WCRR.transform.position); } #endregion #region Spray and Smoke Particles Region //Spray dirt try { if (RoadMat == "Dirt" || RoadMat == "Air") { if (groundedRL && ForwardSlipRL != 0) { if (WCRL.motorTorque > 0) { psSprayLFwd.Stop(); psSprayL.Play(); var vel = psSprayL.velocityOverLifetime; vel.x = WCRL.slipVectorNorm.y * Mathf.Sign(WCRL.motorTorque) * 3; vel.y = 2; vel.z = WCRL.slipVectorNorm.x * Mathf.Abs(WCRL.SlipVectorMagnitude) * 3.5f; peSprayL.rateOverTime = Mathf.Clamp(WCRL.SlipVectorMagnitude * 50, 0, 50); } else //goimg backwards { psSprayL.Stop(); psSprayLFwd.Play(); var vel = psSprayLFwd.velocityOverLifetime; vel.x = WCRL.slipVectorNorm.y * Mathf.Sign(WCRL.motorTorque) * 3; vel.y = Mathf.Abs(WCRL.SlipVectorMagnitude); vel.z = WCRL.slipVectorNorm.x * Mathf.Abs(WCRL.SlipVectorMagnitude) * 3.5f; //peSprayFLFwd.emissionRate = Mathf.Clamp(WCRL.SlipVectorMagnitude * 30, 0, 30); ParticleSystem.EmissionModule e = psSprayLFwd.emission; e.rateOverTime = Mathf.Clamp(WCRL.SlipVectorMagnitude * 30, 0, 30); } } else { psSprayLFwd.Stop(); psSprayL.Stop(); } if (groundedRR && ForwardSlipRR != 0) { if (WCRL.motorTorque > 0) { psSprayRFwd.Stop(); psSprayR.Play(); var vel = psSprayR.velocityOverLifetime; vel.x = WCRR.slipVectorNorm.y * Mathf.Sign(WCRR.motorTorque) * 4; vel.y = 2; vel.z = WCRR.slipVectorNorm.x * Mathf.Abs(WCRR.SlipVectorMagnitude) * 5; peSprayR.rateOverTime = Mathf.Clamp(WCRR.SlipVectorMagnitude * 50, 0, 50); } else { psSprayR.Stop(); psSprayRFwd.Play(); var vel = psSprayRFwd.velocityOverLifetime; vel.x = WCRR.slipVectorNorm.y * Mathf.Sign(WCRR.motorTorque) * 4; vel.y = 2; vel.z = WCRR.slipVectorNorm.x * Mathf.Abs(WCRR.SlipVectorMagnitude) * 5; //peSprayFRFwd.emissionRate = Mathf.Clamp(WCRR.SlipVectorMagnitude * 50, 0, 50); ParticleSystem.EmissionModule e = psSprayRFwd.emission; e.rateOverTime = Mathf.Clamp(WCRR.SlipVectorMagnitude * 30, 0, 30); } } else { psSprayRFwd.Stop(); psSprayR.Stop(); } } else { psSprayR.Stop(); psSprayRFwd.Stop(); psSprayL.Stop(); psSprayLFwd.Stop(); } } catch (Exception e) { Debug.Log(e.ToString()); } //Spray dust on DirtyRoad try { psDustL.Stop(); psDustR.Stop(); if (RoadMat == "DirtyRoad") { psDustL.Play(); psDustR.Play(); float SlipRL = Mathf.Clamp(WCRL.SlipVectorMagnitude, 0, 2f); float SlipRR = Mathf.Clamp(WCRR.SlipVectorMagnitude, 0, 2f); peDustL.rateOverTime = SlipRL * 80f; peDustR.rateOverTime = SlipRR * 80f; psDustL.transform.localPosition = new Vector3(0, -0.4f, -WCRL.forwardFriction.slip / 6); psDustR.transform.localPosition = new Vector3(0, -0.4f, -WCRR.forwardFriction.slip / 6); } else { psDustL.Stop(); psDustR.Stop(); } } catch { } #endregion #region Wheel Ruts and Skidmarks Region //Make Wheel ruts if ((RoadMat == "Dirt" || RoadMat == "DirtyRoad") && groundedRL && WCRL.SlipVectorMagnitude > SkidThresh / 2) { IsRuttingRL = true; } else { IsRuttingRL = false; } //Debug.Log(IsRuttingRL.ToString() + WasRuttingRL.ToString()); if (IsRuttingRL) { if (!WasRuttingRL) { //create a new rut RutLeft = Road.Instance.NextSkidMk(RutLeft); if (RutLeft != null) { RutLeft.SetMaterial(RutMatrl); RutLeft.Width = 0.233f; RutLeftNodeCount = 0; } } if (RutLeft != null) { RutLeft.AddNode(hitRL.point + Vector3.up * 0.05f); } } WasRuttingRL = IsRuttingRL; if ((RoadMat == "Dirt" || RoadMat == "DirtyRoad") && groundedRR && WCRR.SlipVectorMagnitude > SkidThresh / 2) { IsRuttingRR = true; } else { IsRuttingRR = false; } if (IsRuttingRR) { if (!WasRuttingRR) { //create a new rut RutRight = Road.Instance.NextSkidMk(RutRight); if (RutRight != null) { RutRight.SetMaterial(RutMatrl); RutRight.Width = 0.233f; RutRightNodeCount = 0; } } if (RutRight != null) { RutRight.AddNode(hitRR.point + Vector3.up * 0.05f); } } WasRuttingRR = IsRuttingRR; //Skidmarks if (IsSkiddingRL) { if (!WasSkiddingRL) { //create a new rut RutLeft = Road.Instance.NextSkidMk(RutLeft); if (RutLeft != null) { RutLeft.SetMaterial(SkidMatrl); RutLeft.Width = 0.233f; RutLeftNodeCount = 0; } } if (RutLeft != null) { RutLeft.AddNode(hitRL.point + Vector3.up * 0.05f); } } WasSkiddingRL = IsSkiddingRL; if (IsSkiddingRR) { if (!WasSkiddingRR) { //create a new rut RutRight = Road.Instance.NextSkidMk(RutRight); if (RutRight != null) { RutRight.SetMaterial(SkidMatrl); RutRight.Width = 0.233f; RutRightNodeCount = 0; } } if (RutRight != null) { RutRight.AddNode(hitRR.point + Vector3.up * 0.05f); } } WasSkiddingRR = IsSkiddingRR; if (EndSkidmarks) { WasSkiddingRL = false; WasSkiddingRR = false; WasRuttingRL = false; WasRuttingRR = false; EndSkidmarks = false; } #endregion //Skid Sounds if (IsSkiddingRL || IsSkiddingRR) { if (!SkidAudioSource.isPlaying) { SkidAudioSource.Play(); } } else { SkidAudioSource.Stop(); } }
// Update is called once per frame //FixedUpdate is called for every physics calculation void FixedUpdate() { try { Gps.UpdateSegIdx(); } catch { } GetInputFromInputManager(); //The rest of this method controls the car WCRL.motorTorque = v; WCRR.motorTorque = v; //FLWheel.transform.Rotate(WCFR.rpm / 10, 0, 0, Space.Self); //FRWheel.transform.Rotate(WCFR.rpm / 10, 0, 0, Space.Self); //RRWheel.transform.Rotate(WCRR.rpm / 10, 0, 0, Space.Self); //RLWheel.transform.Rotate(WCRL.rpm / 10, 0, 0, Space.Self); WCFL.steerAngle = h; WCFR.steerAngle = h; Quaternion qSteer = Quaternion.Euler(new Vector3(0, 180 + h * 2f, 0)); FRSteering.transform.localRotation = qSteer; FLSteering.transform.localRotation = qSteer; //Adapt the tyre slip according to the road type string RoadMat = ""; WheelFrictionCurve sFriction = WCRL.sidewaysFriction; WheelFrictionCurve fFriction = WCRL.forwardFriction; if (Gps != null) { if (Gps.IsOnRoad) { SegIdx = Gps.CurrSegIdx; RoadMat = Road.Instance.Segments[SegIdx].roadMaterial; if (RoadMat == "Dirt") { fFriction.stiffness = 0.1f; sFriction.stiffness = 0.01f;//hit.collider.material.staticFriction; } else { fFriction.stiffness = 0.5f; sFriction.stiffness = 0.04f; } } else { fFriction.stiffness = 0.1f; sFriction.stiffness = 0.01f; RoadMat = "Dirt"; } } WCFL.forwardFriction = fFriction; WCFR.forwardFriction = fFriction; WCFL.sidewaysFriction = sFriction; WCFR.sidewaysFriction = sFriction; WCRL.sidewaysFriction = sFriction; WCRR.sidewaysFriction = sFriction; float travelL; float travelR; float AntiRoll = AntiRollForce * GetComponent <Rigidbody>().velocity.magnitude; bool groundedFL = WCFL.GetGroundHit(out hitFL); float ForwardSlipFL = hitFL.forwardSlip; float SidewaysSlipFL = hitFL.sidewaysSlip; //float ContactAngle; //WheelFrictionCurve Fric; //Fric = WCFL.forwardFriction; if (groundedFL) { travelL = (-WCFL.transform.InverseTransformPoint(hitFL.point).y - WCFL.radius) / WCFL.suspensionDistance; } else { travelL = 1.0f; } //ContactAngle = Vector3.Angle (Vector3.up,WCFL.transform.InverseTransformPoint(hit.point))*2*Mathf.PI/360; //Fric.stiffness= Mathf.Sin (ContactAngle); bool groundedFR = WCFR.GetGroundHit(out hitFR); float ForwardSlipFR = hitFR.forwardSlip; float SidewaysSlipFR = hitFR.sidewaysSlip; if (groundedFR) { travelR = (-WCFR.transform.InverseTransformPoint(hitFR.point).y - WCFR.radius) / WCFR.suspensionDistance; FRWheel.transform.Rotate((WCFR.rpm) / 10 - ForwardSlipFR * 40, 0, 0, Space.Self); } else { travelR = 1.0f; FRWheel.transform.Rotate((WCFR.rpm) / 10, 0, 0, Space.Self); } float SkidR = Mathf.Abs(SidewaysSlipFR) * (0.7f - travelR); if (Braking) { SkidR += 18.0f * Mathf.Abs(ForwardSlipFR); } else { SkidR += 18.0f * Mathf.Abs(ForwardSlipFR); } if (SkidR > SkidThresh && RoadMat == "Tarmac") { IsSkiddingFR = true; } else { IsSkiddingFR = false; } //ContactAngle = Vector3.Angle (Vector3.up,WCFR.transform.InverseTransformPoint(hit.point))*2*Mathf.PI/360; //Fric.stiffness= Mathf.Sin (ContactAngle); var antiRollForce = (travelL - travelR) * AntiRoll; if (groundedFL) { GetComponent <Rigidbody>().AddForceAtPosition(WCFL.transform.up * antiRollForce, WCFR.transform.position); GetComponent <Rigidbody>().AddForceAtPosition(WCFL.transform.up * -antiRollForce, WCFL.transform.position); } if (groundedFR) { GetComponent <Rigidbody>().AddForceAtPosition(WCFR.transform.up * -antiRollForce, WCFL.transform.position); GetComponent <Rigidbody>().AddForceAtPosition(WCFR.transform.up * antiRollForce, WCFR.transform.position); } //BACK WHEEL ANTI-ROLL BAR AntiRoll = 50f * GetComponent <Rigidbody>().velocity.magnitude; bool groundedRL = WCRL.GetGroundHit(out hitRL); float ForwardSlipRL = hitRL.forwardSlip; float SidewaysSlipRL = hitRL.sidewaysSlip; if (groundedRL) { travelL = (-WCRL.transform.InverseTransformPoint(hitRL.point).y - WCRL.radius) / WCRL.suspensionDistance; RLWheel.transform.Rotate((WCRL.rpm) / 10 - ForwardSlipRL * 40, 0, 0, Space.Self); } else { travelL = 1.0f; RLWheel.transform.Rotate((WCRL.rpm) / 10, 0, 0, Space.Self); } float SkidL = Mathf.Abs(SidewaysSlipRL) * (0.7f - travelL); if (Braking) { SkidL += 18.0f * Mathf.Abs(ForwardSlipRL); } else { SkidL += 18.0f * Mathf.Abs(ForwardSlipRL); } if (SkidL > SkidThresh && RoadMat == "Tarmac") { IsSkiddingRL = true; } else { IsSkiddingRL = false; } bool groundedRR = WCRR.GetGroundHit(out hitRR); float ForwardSlipRR = hitRR.forwardSlip; float SidewaysSlipRR = hitRR.sidewaysSlip; if (groundedRR) { travelR = (-WCRR.transform.InverseTransformPoint(hitRR.point).y - WCRR.radius) / WCRR.suspensionDistance; } else { travelR = 1.0f; } antiRollForce = (travelL - travelR) * AntiRoll; if (groundedRL) { GetComponent <Rigidbody>().AddForceAtPosition(WCRL.transform.up * antiRollForce, WCRR.transform.position); GetComponent <Rigidbody>().AddForceAtPosition(WCRL.transform.up * -antiRollForce, WCRL.transform.position); } if (groundedRR) { GetComponent <Rigidbody>().AddForceAtPosition(WCRR.transform.up * -antiRollForce, WCRL.transform.position); GetComponent <Rigidbody>().AddForceAtPosition(WCRR.transform.up * antiRollForce, WCRR.transform.position); } //Make Wheel ruts try { if (RoadMat == "Dirt" && groundedFL && !hitFL.collider.name.Contains("Car") && hitFL.force > 3200 && Road.Instance.RutCount < 150) { IsRuttingFL = true; } else { IsRuttingFL = false; } if (EndSkidmarks) { RutLeft = null; } if (IsRuttingFL) { if (!WasRuttingFL) { //create a new rut if (RutLeftNodeCount < 50) { GameObject.DestroyImmediate(goRutLeft); Road.Instance.RutCount--; } goRutLeft = new GameObject("RutLeft"); goRutLeft.tag = "Rut"; Road.Instance.RutCount++; RutLeft = goRutLeft.AddComponent <LineRenderer>(); RutLeft.material = RutMatrl; RutLeft.SetWidth(0.2F, 0.2F); RutLeftNodeCount = 0; } RutLeftNodeCount++; RutLeft.SetVertexCount(RutLeftNodeCount); RutLeft.SetPosition(RutLeftNodeCount - 1, hitFL.point); } WasRuttingFL = IsRuttingFL; if (RoadMat == "Dirt" && groundedFR && !hitFR.collider.name.Contains("Car") && hitFR.force > 3000 && Road.Instance.RutCount < 150) { IsRuttingFR = true; } else { IsRuttingFR = false; } if (EndSkidmarks) { RutRight = null; } if (IsRuttingFR) { if (!WasRuttingFR) { //create a new rut if (RutRightNodeCount < 50) { GameObject.DestroyImmediate(goRutRight); Road.Instance.RutCount--; } goRutRight = new GameObject("RutRight"); goRutRight.tag = "Rut"; Road.Instance.RutCount++; RutRight = goRutRight.AddComponent <LineRenderer>(); RutRight.material = RutMatrl; RutRight.SetWidth(0.2F, 0.2F); RutRightNodeCount = 0; } RutRightNodeCount++; RutRight.SetVertexCount(RutRightNodeCount); RutRight.SetPosition(RutRightNodeCount - 1, hitFR.point); } WasRuttingFR = IsRuttingFR; } catch (Exception e) { Debug.Log(e.ToString()); } //Spray dirt try { if (RoadMat == "Dirt") { Quaternion qSprayL = Quaternion.Euler(new Vector3(90 - Mathf.Sign(ForwardSlipFL) * 45, 180 + h * 1.5f, 0)); SprayFL.transform.localRotation = qSprayL; if (groundedFL && ((ForwardSlipFL < 0 && h > 0) || (ForwardSlipFL > 0 && h < 0)) && Mathf.Abs(WCFL.rpm) > 0) { peSprayFL.Play(); peSprayFL.startSpeed = -Mathf.Abs(ForwardSlipFL) * 15; // THis was for the dust - peSprayFL.startSpeed = -Mathf.Abs(ForwardSlipFL) / 2; peSprayFL.emissionRate = (Mathf.Abs(ForwardSlipFL) + Mathf.Abs(SidewaysSlipFL)) * 300; } else { peSprayFL.Stop(); } Quaternion qSprayR = Quaternion.Euler(new Vector3(90 - Mathf.Sign(ForwardSlipFR) * 45, 180 + h * 1.5f, 0)); SprayFR.transform.localRotation = qSprayR; if (groundedFR && ((ForwardSlipFR < 0 && h < 0) || (ForwardSlipFR > 0 && h > 0)) && Mathf.Abs(WCFR.rpm) > 0) { peSprayFR.Play(); peSprayFR.startSpeed = -Mathf.Abs(ForwardSlipFR) * 15; peSprayFR.emissionRate = (Mathf.Abs(ForwardSlipFR) + Mathf.Abs(SidewaysSlipFR)) * 300; } else { peSprayFR.Stop(); } } else { peSprayFR.Stop(); peSprayFL.Stop(); } } catch (Exception e) { Debug.Log(e.ToString()); } //Skidmarks if (EndSkidmarks) { SkidMkLeft = null; SkidMkRight = null; WasSkiddingRL = false; WasSkiddingFR = false; } if (IsSkiddingRL) { if (!WasSkiddingRL) { //create a new rut if (SkidMkLeft != null) { SkidMkLeft.enabled = false; } if (SkidMkLeftNodeCount < 50) { GameObject.DestroyImmediate(goSkidMkLeft); Road.Instance.RutCount--; } goSkidMkLeft = new GameObject("SkidMkLeft"); goSkidMkLeft.tag = "Rut"; Road.Instance.RutCount++; SkidMkLeft = goSkidMkLeft.AddComponent <FlatLineRenderer>(); SkidMkLeft.Init(); SkidMkLeft.SetMaterial(SkidMatrl); SkidMkLeft.Width = 0.1f; SkidMkLeftNodeCount = 0; } SkidMkLeftNodeCount++; SkidMkLeft.AddNode(hitRL.point + Vector3.up * 0.05f); } WasSkiddingRL = IsSkiddingRL; if (IsSkiddingFR) { if (!WasSkiddingFR) { //create a new rut if (SkidMkRightNodeCount < 50) { GameObject.DestroyImmediate(goSkidMkRight); Road.Instance.RutCount--; } goSkidMkRight = new GameObject("SkidMkRight"); goSkidMkRight.tag = "Rut"; Road.Instance.RutCount++; SkidMkRight = goSkidMkRight.AddComponent <FlatLineRenderer>(); SkidMkRight.Init(); SkidMkRight.SetMaterial(SkidMatrl); SkidMkRight.Width = 0.1f; SkidMkRightNodeCount = 0; } SkidMkRightNodeCount++; SkidMkRight.AddNode(hitFR.point + Vector3.up * 0.05f); } WasSkiddingFR = IsSkiddingFR; EndSkidmarks = false; //Braking if (Braking) { WCFL.brakeTorque = 700; WCFR.brakeTorque = 700; WCRL.brakeTorque = 700; WCRR.brakeTorque = 700; } else { WCFL.brakeTorque = 0; WCFR.brakeTorque = 0; WCRL.brakeTorque = 0; WCRR.brakeTorque = 0; } }
// Update is called once per frame //FixedUpdate is called for every physics calculation void FixedUpdate() { GetInputFromInputManager(); //The rest of this method controls the car WCFL.motorTorque = v; WCFR.motorTorque = v; UnityEngine.Profiling.Profiler.BeginSample("RimSpin"); if (_rimSpin) { if (Mathf.Abs(WCFL.rpm) > 300) { _fLRimSpinRenderer.enabled = true; _fLRimRenderer.enabled = false; } else { _fLRimRenderer.enabled = true; _fLRimSpinRenderer.enabled = false; } if (Mathf.Abs(WCRL.rpm) > 300) { _rLRimSpinRenderer.enabled = true; _rLRimRenderer.enabled = false; } else { _rLRimRenderer.enabled = true; _rLRimSpinRenderer.enabled = false; } if (Mathf.Abs(WCFR.rpm) > 300) { _fRRimRenderer.enabled = false; _fRRimSpinRenderer.enabled = true; } else { _fRRimRenderer.enabled = true; _fRRimSpinRenderer.enabled = false; } if (Mathf.Abs(WCRR.rpm) > 300) { _rRRimRenderer.enabled = false; _rRRimSpinRenderer.enabled = true; } else { _rRRimRenderer.enabled = true; _rRRimSpinRenderer.enabled = false; } } UnityEngine.Profiling.Profiler.EndSample(); //Adapt the tyre slip according to the road type if (Gps != null) { RoadMat = Gps.RoadMat; if (TestRoadMat != null) { RoadMat = TestRoadMat; } switch (RoadMat) { case "Tarmac": frontFrict = frontFrictTarmac; rearFrict = rearFrictTarmac; GravelSimulation = false; WashboardSimulation = false; break; case "Washboard": frontFrict = frontFrictTarmac; rearFrict = rearFrictTarmac; GravelSimulation = false; WashboardSimulation = true; break; case "DirtyRoad": frontFrict = frontFrictDirtyRoad; rearFrict = rearFrictDirtyRoad; GravelSimulation = false; WashboardSimulation = false; break; default: frontFrict = frontFrictDirt; rearFrict = rearFrictDirt; GravelSimulation = true; WashboardSimulation = false; break; } //For pendulum turns - if the angular velocity is big, reduce the rear side slip coeff: //PendulumSlipCoeff should be between 1 and 0.7 //Vector3 _desiredVector = Road.Instance.XSecs[Gps.SegIdx + 20].MidPt - Road.Instance.XSecs[Gps.SegIdx + 10].MidPt; float PendulumForceCoeff; float TotSlip = 0; float Divisor = 0; if (WCFL.isGrounded) { float s = Mathf.Abs(WCRL.sideFriction.slip); LSlips.Enqueue(s); LSlipsum += s; if (LSlips.Count > 50) { LSlipsum -= LSlips.Dequeue(); Divisor = 50; } TotSlip = LSlipsum; } if (WCFR.isGrounded) { float rs = Mathf.Abs(WCRR.sideFriction.slip); RSlips.Enqueue(rs); RSlipsum += rs; if (RSlips.Count > 50) { RSlipsum -= RSlips.Dequeue(); Divisor += 50; } TotSlip += RSlipsum; } float MovingAvgSlip; if (Divisor == 0) { MovingAvgSlip = 0.7f; } else { MovingAvgSlip = TotSlip / Divisor; } //MovingAvgSlip stays around 0.01-0.02 and goes up to 0.2 when it breaks away. For a severe skid goes up to 0.7 //Each Fixedframe it's changing by 0.002 to 0.009 //So we can force it to increase fast and drop back slowly SlipQueue.Enqueue(MovingAvgSlip); if (SlipQueue.Count > 50) { DelayedSlip = SlipQueue.Dequeue(); } else { DelayedSlip = MovingAvgSlip; } if (DelayedSlip < MovingAvgSlip) { DelayedSlip = MovingAvgSlip; } if (Mathf.Abs(h - _prevh) > 10) { SlipDelayTimer = 0; } if (SlipDelayTimer < 50) { DelayedSlip = 0.5f; SlipDelayTimer++; } _prevh = h; PendulumForceCoeff = Mathf.Clamp(1 - DelayedSlip * SlipEffect, 0.4f, 1f); WCRL.sideFriction.forceCoefficient = _rearslipCoeff * PendulumForceCoeff; //normally forceCoeff = 5; Bigger = more turning force WCRR.sideFriction.forceCoefficient = _rearslipCoeff * PendulumForceCoeff; //Easy cornering - The GPS can manage the reverse steering float BendAnglePerSec = 0; if (Gps.CurrBend != null) { BendAnglePerSec = Gps.CurrBend.RacelineAnglePerSeg * Gps.SegsPerSec; float CorrectionAnglePerSec = (BendAnglePerSec - _rb.angularVelocity.y * 57.3f); if (Mathf.Sign(CorrectionAnglePerSec) != Mathf.Sign(BendAnglePerSec)) //only apply the correction if oversteering { h += CorrectionAnglePerSec; } h = Mathf.Clamp(h, -40, 40); } //Feather the throttle if were understeering if (WCFL.sideFriction.slip > frontFrict.keys[1].time || WCFR.sideFriction.slip > frontFrict.keys[1].time) { WCFL.motorTorque *= 0.7f; WCFL.motorTorque *= 0.7f; } //txtTrace.text = "FSlip=" + WCFL.SlipVectorMagnitude; //txtTrace.color = (WCFL.SlipVectorMagnitude > frontFrict.keys[1].time)? Color.red: Color.yellow; //txtTrace2.text = "RSlip" + WCRL.SlipVectorMagnitude; //txtTrace2.color = (WCRL.SlipVectorMagnitude > rearFrict.keys[1].time) ? Color.red : Color.yellow; } else { frontFrict = frontFrictDirt; rearFrict = rearFrictDirt; RoadMat = "Dirt"; GravelSimulation = true; WashboardSimulation = false; } //Comment out for testing WCFL.forwardFriction.frictionCurve = frontFrict; WCFR.forwardFriction.frictionCurve = frontFrict; WCRL.forwardFriction.frictionCurve = rearFrict; WCRR.forwardFriction.frictionCurve = rearFrict; WCFL.GravelSimulation = GravelSimulation; WCFR.GravelSimulation = GravelSimulation; WCRL.GravelSimulation = GravelSimulation; WCRR.GravelSimulation = GravelSimulation; WCFL.WashboardSimulation = WashboardSimulation; WCFR.WashboardSimulation = WashboardSimulation; WCRL.WashboardSimulation = WashboardSimulation; WCRR.WashboardSimulation = WashboardSimulation; WCFL.steerAngle = h; WCFR.steerAngle = h; //Limit max speed in reverse if (WCFL.rpm < -300) { WCFL.motorTorque = Mathf.Clamp(WCFL.motorTorque, 0, 10000); WCFR.motorTorque = Mathf.Clamp(WCFR.motorTorque, 0, 10000); } float travelL; float travelR; float AntiRoll = AntiRollForce * GetComponent <Rigidbody>().velocity.magnitude; bool groundedFL = WCFL.GetGroundHit(out hitFL); float ForwardSlipFL = hitFL.forwardSlip; float SidewaysSlipFL = hitFL.sidewaysSlip; if (groundedFL) { travelL = (-WCFL.transform.InverseTransformPoint(hitFL.point).y - WCFL.radius) / WCFL.springLength; //if (hitFL.force > 150000 && FLRim != null) //{ // GameObject.Destroy(FLRim); //} } else { travelL = 1.0f; } float SkidL = Mathf.Abs(SidewaysSlipFL) + Mathf.Abs(ForwardSlipFL); if (SkidL > SkidThresh && RoadMat == "Tarmac") { IsSkiddingFL = true; } else { IsSkiddingFL = false; SkidAudioSource.Stop(); } bool groundedFR = WCFR.GetGroundHit(out hitFR); float ForwardSlipFR = hitFR.forwardSlip; float SidewaysSlipFR = hitFR.sidewaysSlip; if (groundedFR) { travelR = (-WCFR.transform.InverseTransformPoint(hitFR.point).y - WCFR.radius) / WCFR.springLength; } else { travelR = 1.0f; } float SkidR = Mathf.Abs(SidewaysSlipFR) + Mathf.Abs(ForwardSlipFR); if (SkidR > SkidThresh && RoadMat == "Tarmac") { IsSkiddingFR = true; } else { IsSkiddingFR = false; } //ContactAngle = Vector3.Angle (Vector3.up,WCFR.transform.InverseTransformPoint(hit.point))*2*Mathf.PI/360; //Fric.stiffness= Mathf.Sin (ContactAngle); var antiRollForce = (travelL - travelR) * AntiRoll; if (groundedFL) { GetComponent <Rigidbody>().AddForceAtPosition(WCFL.transform.up * antiRollForce, WCFR.transform.position); GetComponent <Rigidbody>().AddForceAtPosition(WCFL.transform.up * -antiRollForce, WCFL.transform.position); } if (groundedFR) { GetComponent <Rigidbody>().AddForceAtPosition(WCFR.transform.up * -antiRollForce, WCFL.transform.position); GetComponent <Rigidbody>().AddForceAtPosition(WCFR.transform.up * antiRollForce, WCFR.transform.position); } //BACK WHEEL ANTI-ROLL BAR //took this out dont know what it was for? //AntiRoll = 50f * GetComponent<Rigidbody>().velocity.magnitude; bool groundedRL = WCRL.GetGroundHit(out hitRL); float ForwardSlipRL = hitRL.forwardSlip; float SidewaysSlipRL = hitRL.sidewaysSlip; if (groundedRL) { travelL = (-WCRL.transform.InverseTransformPoint(hitRL.point).y - WCRL.radius) / WCRL.springLength; } else { travelL = 1.0f; } bool groundedRR = WCRR.GetGroundHit(out hitRR); float ForwardSlipRR = hitRR.forwardSlip; float SidewaysSlipRR = hitRR.sidewaysSlip; if (groundedRR) { travelR = (-WCRR.transform.InverseTransformPoint(hitRR.point).y - WCRR.radius) / WCRR.springLength; } else { travelR = 1.0f; } antiRollForce = (travelL - travelR) * AntiRoll; if (groundedRL) { GetComponent <Rigidbody>().AddForceAtPosition(WCRL.transform.up * antiRollForce, WCRR.transform.position); GetComponent <Rigidbody>().AddForceAtPosition(WCRL.transform.up * -antiRollForce, WCRL.transform.position); } if (groundedRR) { GetComponent <Rigidbody>().AddForceAtPosition(WCRR.transform.up * -antiRollForce, WCRL.transform.position); GetComponent <Rigidbody>().AddForceAtPosition(WCRR.transform.up * antiRollForce, WCRR.transform.position); } #region Spray and Smoke Particles Region //Spray dirt try { if (RoadMat == "Dirt") { //+ve ForwardSlip means spraying backwards //+ve SteerAngle = Right psSprayL.transform.localRotation = Quaternion.Euler(45, WCFL.steerAngle + (ForwardSlipFL >= 0 ? 0 : 180), 0); if (groundedFL && ((ForwardSlipFL < 0 && h < -0.01f) || (ForwardSlipFL > 0 && h > 0.01f)) && Mathf.Abs(WCFL.rpm) > 0) { psSprayL.Play(); pmSprayL.startSpeed = -Mathf.Clamp((Mathf.Abs(ForwardSlipFL) + Mathf.Abs(SidewaysSlipFL)) * 14, 0, 7); // THis was for the dust - peSprayFL.startSpeed = -Mathf.Abs(ForwardSlipFL) / 2; peSprayL.rateOverTime = (Mathf.Abs(ForwardSlipFL) + Mathf.Abs(SidewaysSlipFL)) * 100; } else { psSprayL.Stop(); pmSprayL.startSpeed = 0; } psSprayR.transform.localRotation = Quaternion.Euler(45, WCFR.steerAngle + (ForwardSlipFR >= 0 ? 0 : 180), 0); if (groundedFR && ((ForwardSlipFR < 0 && h > 0.01f) || (ForwardSlipFR > 0 && h < -0.01f)) && Mathf.Abs(WCFR.rpm) > 0) { psSprayR.Play(); pmSprayR.startSpeed = -Mathf.Clamp((Mathf.Abs(ForwardSlipFR) + Mathf.Abs(SidewaysSlipFR)) * 14, 0, 7); peSprayR.rateOverTime = (Mathf.Abs(ForwardSlipFR) + Mathf.Abs(SidewaysSlipFR)) * 100; } else { psSprayR.Stop(); pmSprayR.startSpeed = 0; } } else { psSprayR.Stop(); psSprayL.Stop(); psSprayR.startSpeed = 0; psSprayL.startSpeed = 0; } } catch (Exception e) { Debug.Log(e.ToString()); } //Spray dust on DirtyRoad try { psDustL.Stop(); psDustR.Stop(); if (RoadMat == "DirtyRoad") { psDustL.Play(); psDustR.Play(); float SlipFL = Mathf.Clamp(WCFL.SlipVectorMagnitude, 0, 0.1f); float SlipFR = Mathf.Clamp(WCFR.SlipVectorMagnitude, 0, 0.1f); peDustL.rateOverTime = SlipFL * 500f; peDustR.rateOverTime = SlipFR * 500f; psDustL.transform.localPosition = new Vector3(0, -0.4f, -WCFL.forwardFriction.slip / 6); psDustR.transform.localPosition = new Vector3(0, -0.4f, -WCFR.forwardFriction.slip / 6); } else { psDustL.Stop(); psDustR.Stop(); } } catch { } #endregion #region Wheel ruts and Skid marks //Make Wheel ruts try { if ((RoadMat == "DirtyRoad" && groundedFL && (Math.Abs(ForwardSlipFL) > 1 || Math.Abs(SidewaysSlipFL) > 1 || hitFL.force > 3000)) || (RoadMat == "Dirt" && groundedFL && (Math.Abs(ForwardSlipFL) > 0.8f || Math.Abs(SidewaysSlipFL) > 0.5f || hitFL.force > 3000))) { IsRuttingFL = true; } else { IsRuttingFL = false; } if (IsRuttingFL) { if (!WasRuttingFL) { //create a new rut if (RutLeft != null) { Destroy(RutLeft); } if (RutLeftNodeCount < 20) { GameObject.Destroy(goRutLeft); Road.Instance.RutCount--; } goRutLeft = new GameObject("RutLeft"); goRutLeft.isStatic = true; goRutLeft.tag = "Rut"; Road.Instance.RutCount++; RutLeft = goRutLeft.AddComponent <FlatLineRenderer>(); RutLeft.Init(); RutLeft.SetMaterial(RutMatrl); RutLeft.Width = 0.233f; RutLeftNodeCount = 0; } if (RutLeft != null) { RutLeftNodeCount++; RutLeft.AddNode(hitFL.point + Vector3.up * 0.05f); } } WasRuttingFL = IsRuttingFL; if ((RoadMat == "DirtyRoad" && groundedFR && (Math.Abs(ForwardSlipFR) > 1 || Math.Abs(SidewaysSlipFR) > 1 || hitFR.force > 3000)) || (RoadMat == "Dirt" && groundedFR && (Math.Abs(ForwardSlipFR) > 0.6f || Math.Abs(SidewaysSlipFR) > 0.6f || hitFR.force > 3000))) { IsRuttingFR = true; } else { IsRuttingFR = false; } if (IsRuttingFR) { if (!WasRuttingFR) { //create a new rut if (RutRightNodeCount < 20) { GameObject.Destroy(goRutRight); Road.Instance.RutCount--; } goRutRight = new GameObject("RutRight"); goRutRight.isStatic = true; goRutRight.tag = "Rut"; Road.Instance.RutCount++; RutRight = goRutRight.AddComponent <FlatLineRenderer>(); RutRight.Init(); RutRight.SetMaterial(RutMatrl); RutRight.Width = 0.233f; RutRightNodeCount = 0; } if (RutRight != null) { RutRightNodeCount++; RutRight.AddNode(hitFR.point + Vector3.up * 0.05f); } } WasRuttingFR = IsRuttingFR; } catch (Exception e) { Debug.Log(e.ToString()); } //Skid Sounds if (IsSkiddingFL || IsSkiddingFR) { if (!SkidAudioSource.isPlaying) { SkidAudioSource.Play(); } } else { SkidAudioSource.Stop(); } //Skidmarks if (IsSkiddingFL) { if (!WasSkiddingFL) { //create a new rut if (SkidMkLeft != null) { SkidMkLeft.enabled = false; Destroy(SkidMkLeft); } if (SkidMkLeftNodeCount < 50) { GameObject.Destroy(goSkidMkLeft); Road.Instance.RutCount--; } goSkidMkLeft = new GameObject("SkidMkLeft"); goSkidMkLeft.isStatic = true; goSkidMkLeft.tag = "Rut"; Road.Instance.RutCount++; SkidMkLeft = goSkidMkLeft.AddComponent <FlatLineRenderer>(); SkidMkLeft.Init(); SkidMkLeft.SetMaterial(SkidMatrl); SkidMkLeft.Width = 0.15f; SkidMkLeftNodeCount = 0; } SkidMkLeftNodeCount++; SkidMkLeft.AddNode(hitFL.point + Vector3.up * 0.05f); } WasSkiddingFL = IsSkiddingFL; if (IsSkiddingFR) { if (!WasSkiddingFR) { //create a new rut if (SkidMkRight != null) { Destroy(SkidMkRight); } if (SkidMkRightNodeCount < 50) { GameObject.DestroyImmediate(goSkidMkRight); Road.Instance.RutCount--; } goSkidMkRight = new GameObject("SkidMkRight"); goSkidMkRight.isStatic = true; goSkidMkRight.tag = "Rut"; Road.Instance.RutCount++; SkidMkRight = goSkidMkRight.AddComponent <FlatLineRenderer>(); SkidMkRight.Init(); SkidMkRight.SetMaterial(SkidMatrl); SkidMkRight.Width = 0.15f; SkidMkRightNodeCount = 0; } SkidMkRightNodeCount++; SkidMkRight.AddNode(hitFR.point + Vector3.up * 0.05f); } WasSkiddingFR = IsSkiddingFR; if (EndSkidmarks) { WasSkiddingFL = false; WasSkiddingFR = false; WasRuttingFL = false; WasRuttingFR = false; EndSkidmarks = false; } #endregion WCFL.brakeTorque = BrakeForce; WCFR.brakeTorque = BrakeForce; WCRL.brakeTorque = BrakeForce; WCRR.brakeTorque = BrakeForce; }
// Update is called once per frame //FixedUpdate is called for every physics calculation void FixedUpdate() { GetInputFromInputManager(); //The rest of this method controls the car WCFL.brakeTorque = BrakeForce; WCFR.brakeTorque = BrakeForce; WCRL.brakeTorque = BrakeForce; WCRR.brakeTorque = BrakeForce; WCRL.motorTorque = v; WCRR.motorTorque = v; if (WCRL.rpm < -300) { WCRL.motorTorque = Mathf.Clamp(WCRL.motorTorque, 0, 10000); WCRR.motorTorque = Mathf.Clamp(WCRR.motorTorque, 0, 10000); } if (_rimSpin) { if (Mathf.Abs(WCFL.rpm) > 300) { _fLRimSpinRenderer.enabled = true; _fLRimRenderer.enabled = false; } else { _fLRimRenderer.enabled = true; _fLRimSpinRenderer.enabled = false; } if (Mathf.Abs(WCRL.rpm) > 300) { _rLRimSpinRenderer.enabled = true; _rLRimRenderer.enabled = false; } else { _rLRimRenderer.enabled = true; _rLRimSpinRenderer.enabled = false; } if (Mathf.Abs(WCFR.rpm) > 300) { _fRRimRenderer.enabled = false; _fRRimSpinRenderer.enabled = true; } else { _fRRimRenderer.enabled = true; _fRRimSpinRenderer.enabled = false; } if (Mathf.Abs(WCRR.rpm) > 300) { _rRRimRenderer.enabled = false; _rRRimSpinRenderer.enabled = true; } else { _rRRimRenderer.enabled = true; _rRRimSpinRenderer.enabled = false; } } //Adapt the tyre slip according to the road type bool GravelSimulation = false; if (Gps != null) { RoadMat = Gps.RoadMat; switch (RoadMat) { case "Tarmac": case "Washboard": frontFrict = frontFrictTarmac; rearFrict = rearFrictTarmac; break; case "DirtyRoad": frontFrict = frontFrictDirtyRoad; rearFrict = rearFrictDirtyRoad; //GravelSimulation = true; break; default: frontFrict = frontFrictDirt; rearFrict = rearFrictDirt; GravelSimulation = true; break; } Vector3 _vel = _rb.velocity; float _rearSlideSlip = Vector3.Angle(_vel, transform.forward); if (WCRL.angularVelocity > 0) { //Easy cornering - The GPS can manage the reverse steering float BendAnglePerSec = 0; if (Gps.CurrBend != null) { BendAnglePerSec = Gps.CurrBend.AnglePerSeg * Gps.SegsPerSec; float CorrectionAnglePerSec = (BendAnglePerSec - _rb.angularVelocity.y * 57.3f); if (Mathf.Sign(CorrectionAnglePerSec) != Mathf.Sign(BendAnglePerSec)) //only apply the correction if oversteering { h += CorrectionAnglePerSec; } h = Mathf.Clamp(h, -40, 40); } //For Rear wheel drive we give a little extra torque when reverse steering in a skid Vector3 cross = Vector3.Cross(_vel, transform.forward); WCRL.fFriction.forceCoefficient = FCoef; WCRR.fFriction.forceCoefficient = FCoef; WCRL.sideFriction.forceCoefficient = SCoef; WCRR.sideFriction.forceCoefficient = SCoef; if (Mathf.Abs(h) < 3 || Mathf.Sign(cross.y) != Mathf.Sign(h)) { WCRL.motorTorque *= (1 + Mathf.Abs(_rearSlideSlip) / 90f); WCRR.motorTorque *= (1 + Mathf.Abs(_rearSlideSlip) / 90f); WCRL.fFriction.forceCoefficient *= (1 + Mathf.Abs(_rearSlideSlip) / 90f); WCRR.fFriction.forceCoefficient *= (1 + Mathf.Abs(_rearSlideSlip) / 90f); } } //going forwrds //spinout //if (_rearSlideSlip > 90) { WCRL.sFriction.forceCoefficient = 0.2f; WCRR.sFriction.forceCoefficient = 0.2f; } } else //if gps is null { frontFrict = frontFrictDirt; rearFrict = rearFrictDirt; RoadMat = "Dirt"; } if (frontFrict == frontFrictTarmac) { h = h / (1f + GetComponent <Rigidbody>().velocity.magnitude / 35); //The last number: bigger means sharper turns at high speed } WCFL.steerAngle = h; WCFR.steerAngle = h; //For testing comment out this block WCFL.forwardFriction.frictionCurve = frontFrict; WCFR.forwardFriction.frictionCurve = frontFrict; WCRL.forwardFriction.frictionCurve = rearFrict; WCRR.forwardFriction.frictionCurve = rearFrict; WCFL.GravelSimulation = GravelSimulation; WCFR.GravelSimulation = GravelSimulation; WCRL.GravelSimulation = GravelSimulation; WCRR.GravelSimulation = GravelSimulation; #region Anti-Roll bar Region float travelL; float travelR; float AntiRoll = AntiRollForce * GetComponent <Rigidbody>().velocity.magnitude; bool groundedFL = WCFL.GetGroundHit(out hitFL); //float ContactAngle; //WheelFrictionCurve Fric; //Fric = WCFL.forwardFriction; if (groundedFL) { travelL = WCFL.springCompression - 1; } else { travelL = 1.0f; } bool groundedFR = WCFR.GetGroundHit(out hitFR); if (groundedFR) { travelR = WCFR.springCompression - 1; } else { travelR = 1.0f; } var antiRollForce = (travelL - travelR) * AntiRoll; if (groundedFL) { GetComponent <Rigidbody>().AddForceAtPosition(WCFL.transform.up * antiRollForce, WCFR.transform.position); GetComponent <Rigidbody>().AddForceAtPosition(WCFL.transform.up * -antiRollForce, WCFL.transform.position); } if (groundedFR) { GetComponent <Rigidbody>().AddForceAtPosition(WCFR.transform.up * -antiRollForce, WCFL.transform.position); GetComponent <Rigidbody>().AddForceAtPosition(WCFR.transform.up * antiRollForce, WCFR.transform.position); } //BACK WHEEL ANTI-ROLL BAR bool groundedRL = WCRL.GetGroundHit(out hitRL); bool groundedRR = WCRR.GetGroundHit(out hitRR); float ForwardSlipRL = hitRL.forwardSlip; float SidewaysSlipRL = hitRL.sidewaysSlip; if (groundedRL) { travelL = WCRL.springCompression - 1; } else { travelL = 1.0f; } if (WCRL.SlipVectorMagnitude > SkidThresh && RoadMat == "Tarmac") { IsSkiddingRL = true; } else { IsSkiddingRL = false; } float ForwardSlipRR = hitRR.forwardSlip; float SidewaysSlipRR = hitRR.sidewaysSlip; if (groundedRR) { travelR = WCRR.springCompression - 1; } else { travelR = 1.0f; } if (WCRR.SlipVectorMagnitude > SkidThresh && RoadMat == "Tarmac") { IsSkiddingRR = true; } else { IsSkiddingRR = false; } antiRollForce = (travelL - travelR) * AntiRoll; if (groundedRL) { GetComponent <Rigidbody>().AddForceAtPosition(WCRL.transform.up * antiRollForce, WCRR.transform.position); GetComponent <Rigidbody>().AddForceAtPosition(WCRL.transform.up * -antiRollForce, WCRL.transform.position); } if (groundedRR) { GetComponent <Rigidbody>().AddForceAtPosition(WCRR.transform.up * -antiRollForce, WCRL.transform.position); GetComponent <Rigidbody>().AddForceAtPosition(WCRR.transform.up * antiRollForce, WCRR.transform.position); } #endregion #region Spray and Smoke Particles Region //Spray dirt try { if (RoadMat == "Dirt" || RoadMat == "Air") { if (groundedRL && ForwardSlipRL != 0) { if (WCRL.motorTorque > 0) { psSprayLFwd.Stop(); psSprayL.Play(); var vel = psSprayL.velocityOverLifetime; vel.x = WCRL.slipVectorNorm.y * Mathf.Sign(WCRL.motorTorque) * 7; vel.y = 2; vel.z = WCRL.slipVectorNorm.x * Mathf.Abs(WCRL.SlipVectorMagnitude) * 7; peSprayL.rateOverTime = Mathf.Clamp(WCRL.SlipVectorMagnitude * 50, 0, 50); } else //goimg backwards { psSprayL.Stop(); psSprayLFwd.Play(); var vel = psSprayLFwd.velocityOverLifetime; vel.x = WCRL.slipVectorNorm.y * Mathf.Sign(WCRL.motorTorque) * 7; vel.y = 2; vel.z = WCRL.slipVectorNorm.x * Mathf.Abs(WCRL.SlipVectorMagnitude) * 7; ParticleSystem.EmissionModule e = psSprayLFwd.emission; e.rateOverTime = Mathf.Clamp(WCRL.SlipVectorMagnitude * 30, 0, 30); } } else { psSprayLFwd.Stop(); psSprayL.Stop(); } if (groundedRR && ForwardSlipRR != 0) { if (WCRL.motorTorque > 0) { psSprayRFwd.Stop(); psSprayR.Play(); var vel = psSprayR.velocityOverLifetime; vel.x = WCRR.slipVectorNorm.y * Mathf.Sign(WCRR.motorTorque) * 7; vel.y = 2; vel.z = WCRR.slipVectorNorm.x * Mathf.Abs(WCRR.SlipVectorMagnitude) * 7; peSprayR.rateOverTime = Mathf.Clamp(WCRR.SlipVectorMagnitude * 50, 0, 50); } else { psSprayR.Stop(); psSprayRFwd.Play(); var vel = psSprayRFwd.velocityOverLifetime; vel.x = WCRR.slipVectorNorm.y * Mathf.Sign(WCRR.motorTorque) * 7; vel.y = 2; vel.z = WCRR.slipVectorNorm.x * Mathf.Abs(WCRR.SlipVectorMagnitude) * 7; ParticleSystem.EmissionModule e = psSprayRFwd.emission; e.rateOverTime = Mathf.Clamp(WCRR.SlipVectorMagnitude * 30, 0, 30); } } else { psSprayRFwd.Stop(); psSprayR.Stop(); } //[email protected] } else { psSprayR.Stop(); psSprayRFwd.Stop(); psSprayL.Stop(); psSprayLFwd.Stop(); } } catch (Exception e) { Debug.Log(e.ToString()); } //Spray dust on DirtyRoad try { psDustL.Stop(); psDustR.Stop(); if (RoadMat == "DirtyRoad") { psDustL.Play(); psDustR.Play(); float SlipRL = Mathf.Clamp(WCRL.SlipVectorMagnitude, 0, 2f); float SlipRR = Mathf.Clamp(WCRR.SlipVectorMagnitude, 0, 2f); ParticleSystem.EmissionModule emRL = psDustL.emission; peDustL.rateOverTime = SlipRL * 80f; peDustR.rateOverTime = SlipRR * 80f; psDustL.transform.localPosition = new Vector3(0, -0.4f, -WCRL.forwardFriction.slip / 6); psDustR.transform.localPosition = new Vector3(0, -0.4f, -WCRR.forwardFriction.slip / 6); } else { psDustL.Stop(); psDustR.Stop(); } } catch { } #endregion #region Wheel Ruts and Skidmarks Region //Make Wheel ruts try { if ((RoadMat == "Dirt" || RoadMat == "DirtyRoad") && groundedRL && ((Math.Abs(ForwardSlipRL) > 1f || Math.Abs(SidewaysSlipRL) > 0.1f) && WCRL.springCompression < 0.6f)) { IsRuttingFL = true; } else { IsRuttingFL = false; } if (IsRuttingFL) { if (!WasRuttingFL) { //create a new rut if (RutLeft != null) { Destroy(RutLeft); } if (RutLeftNodeCount < 20) { GameObject.Destroy(goRutLeft); Road.Instance.RutCount--; } goRutLeft = new GameObject("RutLeft"); goRutLeft.transform.SetParent(_trSkidMarks); goRutLeft.isStatic = true; goRutLeft.tag = "Rut"; Road.Instance.RutCount++; RutLeft = goRutLeft.AddComponent <FlatLineRenderer>(); RutLeft.Init(); RutLeft.SetMaterial(RutMatrl); RutLeft.Width = 0.233f; RutLeftNodeCount = 0; } if (RutLeft != null) { RutLeftNodeCount++; RutLeft.AddNode(hitRL.point + Vector3.up * 0.05f); } } WasRuttingFL = IsRuttingFL; if ((RoadMat == "Dirt" || RoadMat == "DirtyRoad") && groundedRR && ((Math.Abs(ForwardSlipRR) > 1f || Math.Abs(SidewaysSlipRR) > 0.1f) && WCRR.springCompression < 0.6f)) { IsRuttingFR = true; } else { IsRuttingFR = false; } if (IsRuttingFR) { if (!WasRuttingFR) { //create a new rut if (RutRightNodeCount < 20) { GameObject.Destroy(goRutRight); Road.Instance.RutCount--; } goRutRight = new GameObject("RutRight"); goRutRight.transform.SetParent(_trSkidMarks); goRutRight.isStatic = true; goRutRight.tag = "Rut"; Road.Instance.RutCount++; RutRight = goRutRight.AddComponent <FlatLineRenderer>(); RutRight.Init(); RutRight.SetMaterial(RutMatrl); RutRight.Width = 0.233f; RutRightNodeCount = 0; } if (RutRight != null) { RutRightNodeCount++; RutRight.AddNode(hitRR.point + Vector3.up * 0.05f); } } WasRuttingFR = IsRuttingFR; } catch (Exception e) { Debug.Log(e.ToString()); } //Skid Sounds if (IsSkiddingRL || IsSkiddingRR) { if (!SkidAudioSource.isPlaying) { SkidAudioSource.Play(); } } else { SkidAudioSource.Stop(); } //Skidmarks if (IsSkiddingRL) { if (!WasSkiddingRL) { //create a new rut if (SkidMkLeft != null) { SkidMkLeft.enabled = false; Destroy(SkidMkLeft); } if (SkidMkLeftNodeCount < 50) { GameObject.Destroy(goSkidMkLeft); Road.Instance.RutCount--; } goSkidMkLeft = new GameObject("SkidMkLeft"); goSkidMkLeft.transform.SetParent(_trSkidMarks); goSkidMkLeft.isStatic = true; goSkidMkLeft.tag = "Rut"; Road.Instance.RutCount++; SkidMkLeft = goSkidMkLeft.AddComponent <FlatLineRenderer>(); SkidMkLeft.Init(); SkidMkLeft.SetMaterial(SkidMatrl); SkidMkLeft.Width = 0.15f; SkidMkLeftNodeCount = 0; } SkidMkLeftNodeCount++; SkidMkLeft.AddNode(hitRL.point + Vector3.up * 0.05f); } WasSkiddingRL = IsSkiddingRL; if (IsSkiddingRR) { if (!WasSkiddingRR) { //create a new rut if (SkidMkRight != null) { Destroy(SkidMkRight); } if (SkidMkRightNodeCount < 50) { GameObject.DestroyImmediate(goSkidMkRight); Road.Instance.RutCount--; } goSkidMkRight = new GameObject("SkidMkRight"); goSkidMkRight.transform.SetParent(_trSkidMarks); goSkidMkRight.isStatic = true; goSkidMkRight.tag = "Rut"; Road.Instance.RutCount++; SkidMkRight = goSkidMkRight.AddComponent <FlatLineRenderer>(); SkidMkRight.Init(); SkidMkRight.SetMaterial(SkidMatrl); SkidMkRight.Width = 0.15f; SkidMkRightNodeCount = 0; } SkidMkRightNodeCount++; SkidMkRight.AddNode(hitRR.point + Vector3.up * 0.05f); } WasSkiddingRR = IsSkiddingRR; if (EndSkidmarks) { WasSkiddingRL = false; WasSkiddingRR = false; WasRuttingFL = false; WasRuttingFR = false; EndSkidmarks = false; } #endregion }