public void FixedUpdate() { // Update different classes transmission.Main(this); engine.Main(this); sound.Main(this); lights.Main(this); smoke.Main(this); inputs.Main(this); motorAxleCount = countPoweredAxles(); //remove this line if you won't change number of powered axles during gameplay previousSpeed = speed; //for load calculation velocity = transform.InverseTransformDirection(this.GetComponent <Rigidbody>().velocity).z; // -...+ speed = Mathf.Abs(velocity); // 0...+ direction = velocity >= 0 ? 1 : -1; if (transmission.gear != 0) // reverse gear neds reverse inputs { maxAvailableTorque = transmission.toWheelTorque * inputs.yAxis; } else { maxAvailableTorque = transmission.toWheelTorque * -inputs.yAxis; } float steering = 0; if (FollowPath) { bool finishedPath = currentPathObj >= path.Count; if (finishedPath) { inputs.xAxis = 0; speed = 0; speedSensitiveSteering = 0; brake = true; brakeTorque = maxBrakeTorque; sound.volumeScale = 0.3f; } else { Vector3 steerVector = transform.InverseTransformPoint(new Vector3(((Transform)path [currentPathObj]).position.x, transform.position.y, ((Transform)path [currentPathObj]).position.z)); // ao chegar em um gameObject o carro precisa ir para o proximo do path if (steerVector.magnitude <= distFromPath) { currentPathObj++; // if (currentPathObj >= path.Count) // currentPathObj = 0; } const float steeringDumper = 0.3f; // change max steering based on current speed steering = maxSteeringAngle * steeringDumper * (steerVector.x / steerVector.magnitude); } } else { // change max steering based on current speed steering = (maxSteeringAngle / (((speed / 100) * speedSensitiveSteering) + 1)) * inputs.xAxis; } // get axle speed for final speed calculation foreach (AxleInfo axleInfo in axleInfos) { axleInfo.axleRpm = (Mathf.Abs(axleInfo.leftWheel.collider.rpm) + Mathf.Abs(axleInfo.rightWheel.collider.rpm)) / 2; } /* AWD SYSTEM */ if (awd) { #region Torque distribution /* TORQUE DISTRIBUTION BETWEEN AXLES * maxAvailableTorque is spread onto axles depending on rotation speed */ //get rpm and motor value for each axle float[] rpms = new float[axleInfos.Count]; bool[] motorEnabled = new bool[axleInfos.Count]; //enable torque distribution if axle.motor = true for (int i = 0; i < axleInfos.Count; i++) { rpms[i] = axleInfos[i].axleRpm; motorEnabled[i] = axleInfos[i].motor; } //put rpm values into torque splitter, result is torque array float[] torqueArr; torqueArr = TorqueSplit(motorEnabled, rpms, maxAvailableTorque); for (int i = 0; i < axleInfos.Count; i++) { if (motorEnabled[i]) { axleInfos[i].torque = torqueArr[i]; } } /* TORQUE DISTRIBUTION BETWEEN WHEELS */ debTorque = 0; foreach (AxleInfo axleInfo in axleInfos) { float[] wheelTorqueArr; wheelTorqueArr = TorqueSplit(new bool[] { true, true }, new float[] { axleInfo.rightWheel.collider.rpm, axleInfo.leftWheel.collider.rpm }, axleInfo.torque); if (axleInfo.rightWheel.collider.isGrounded) { axleInfo.rightWheel.torque = wheelTorqueArr[0]; } else { axleInfo.rightWheel.torque = 0; } if (axleInfo.leftWheel.collider.isGrounded) { axleInfo.leftWheel.torque = wheelTorqueArr[1]; } else { axleInfo.leftWheel.torque = 0; } debTorque += axleInfo.torque; } #endregion } /* NOT AWD ***/ else { foreach (AxleInfo axleInfo in axleInfos) { if (axleInfo.motor) { axleInfo.torque = maxAvailableTorque / motorAxleCount; axleInfo.leftWheel.torque = axleInfo.torque / 2; axleInfo.rightWheel.torque = axleInfo.torque / 2; } } } // WHEEL SLIPPING // set wheel slip if any exists to disable shifting wheelSlip = false; foreach (AxleInfo axleInfo in axleInfos) { if (DetectWheelSlip(axleInfo.leftWheel, speed)) { axleInfo.leftWheel.torque = 0; // acts out as mechanical loss when no power applied, spins down the wheel } if (DetectWheelSlip(axleInfo.rightWheel, speed)) { axleInfo.rightWheel.torque = 0; } } foreach (AxleInfo axleInfo in axleInfos) { wheelSlip = axleInfo.leftWheel.slip ? true : wheelSlip; wheelSlip = axleInfo.rightWheel.slip ? true : wheelSlip; if (wheelSlip) { break; } } #region Collider update // UPDATE COLLIDERS WITH CALCULATED VALUES foreach (AxleInfo axleInfo in axleInfos) { // apply steering to colliders if (axleInfo.steering) { axleInfo.leftWheel.collider.steerAngle = steering * axleInfo.steerCoeff; axleInfo.rightWheel.collider.steerAngle = steering * axleInfo.steerCoeff; } // if axle has motor enabled apply torque values to wheels if (axleInfo.motor) { axleInfo.leftWheel.collider.motorTorque = axleInfo.leftWheel.torque; axleInfo.rightWheel.collider.motorTorque = axleInfo.rightWheel.torque; } else { axleInfo.torque = 0; axleInfo.leftWheel.collider.motorTorque = 0; axleInfo.rightWheel.collider.motorTorque = 0; } #region Braking /* BRAKING SECTION */ // if brake enabled calculate and apply brake torque to wheels; if ((Mathf.Abs(inputs.yAxis) > 0.2f && inputs.direction != direction && speed > 0.2f)) { brake = true; brakeTorque = maxBrakeTorque; } if (brake) { #region ABS // abs active if ((abs && speed > 0.5f)) { if (Mathf.Abs(axleInfo.leftWheel.collider.rpm) < (speed * 2)) { axleInfo.leftWheel.brakeTorque = 0; } else { axleInfo.leftWheel.brakeTorque = brakeTorque / 4; } if (Mathf.Abs(axleInfo.rightWheel.collider.rpm) < (speed * 5)) { axleInfo.rightWheel.brakeTorque = 0; } else { axleInfo.rightWheel.brakeTorque = brakeTorque / 4; } } #endregion // no abs else { axleInfo.leftWheel.brakeTorque = brakeTorque / 4; axleInfo.rightWheel.brakeTorque = brakeTorque / 4; } axleInfo.leftWheel.collider.brakeTorque = axleInfo.leftWheel.brakeTorque; axleInfo.rightWheel.collider.brakeTorque = axleInfo.rightWheel.brakeTorque; } else { // release brakes when no brake applyed axleInfo.leftWheel.collider.brakeTorque = 0; axleInfo.rightWheel.collider.brakeTorque = 0; } #endregion //Update wheel visual rotation and position } #endregion //Update rotation and position of wheels UpdateWheelVisuals(axleInfos); }