Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
0
Question by sooraj · May 30, 2015 at 05:13 PM · scripting problemscriptingbasicscarcar-tutorial

How to modify the below script to manual transmission of gears?

hey guys this script is designed for automatic transmission of gears for mobile. when the accelerator is pressed the car moves forward and after it reaches a certain speed the gear changes. and the car goes reverse when brake is pressed. I want the the script to be modified for manual transmission with a button.

 using UnityEngine;
 
 namespace UnitySampleAssets.Vehicles.Car
 {
     public class CarController : MonoBehaviour
     {
 
         // This car component is designed to be used on a gameobject which has wheels attached.
         // The wheels must be child objects, and each have a Wheel script attached, and a WheelCollider component.
 
         // Even though wheelcolliders have their own settings for grip loss, this car script (and its accompanying
         // wheel scripts) modify the settings on the wheelcolliders at runtime, to give a more exaggerated and fun
         // experience, allowing burnouts and drifting behavior in a way that is not readily achievable using
         // constant values on wheelcolliders alone.
 
         // The code priorities fun over realism, and although a gears system is included, it is not used to 
         // 'drive' the engine. Instead, the current revs and gear are calculated retrospectively based
         // on the car's current speed. These gear and rev values can then be read and used by a GUI or Sound component.
 
 
         [SerializeField] private float maxSteerAngle = 28; // The maximum angle the car can steer
         [SerializeField] private float steeringResponseSpeed = 200; // how fast the steering responds
         [SerializeField] [Range(0, 1)] private float maxSpeedSteerAngle = 0.23f;// the reduction in steering angle at max speed
         [SerializeField] [Range(0, .5f)] private float maxSpeedSteerResponse = 0.5f;// the reduction in steer response at max speed
         [SerializeField] private float maxSpeed = 60; // the maximum speed (in meters per second!)
         [SerializeField] private float maxTorque = 35; // the maximum torque of the engine
         [SerializeField] private float minTorque = 10; // the minimum torque of the engine
         [SerializeField] private float brakePower = 40; // how powerful the brakes are at stopping the car
         [SerializeField] private float adjustCentreOfMass = 0.25f; // vertical offset for the centre of mass
         [SerializeField] private Advanced advanced;// container for the advanced setting which will expose as a foldout in the inspector
         [SerializeField] private bool preserveDirectionWhileInAir = false;// flag for if the direction of travel to be preserved in the air (helps cars land in the right direction if doing huge jumps!)
 
         [System.Serializable]
         public class Advanced // the advanced settings for the car controller
         {
             [Range(0, 1)] public float burnoutSlipEffect = 0.4f; // how much the car wheels will slide when burning out
             [Range(0, 1)] public float burnoutTendency = 0.2f; // how likely the car is to burnout 
             [Range(0, 1)] public float spinoutSlipEffect = 0.5f; // how easily the car spins out when turning
             [Range(0, 1)] public float sideSlideEffect = 0.5f; // how easily the car loses sideways grip 
             public float downForce = 30; // the amount of downforce applied (speed is factored in)
             public int numGears = 5; // the number of gears
             [Range(0, 1)] public float gearDistributionBias = 0.2f;// Controls whether the gears are bunched together towards the lower or higher end of the car's range of speed.
             public float steeringCorrection = 2f; // How fast the steering returns to centre with no steering input
             public float oppositeLockSteeringCorrection = 4f;// How fast the steering responds when steer input is in the opposite direction to the current wheel angle
             public float reversingSpeedFactor = 0.3f;// The car's maximum reverse speed, as a proportion of its max forward speed.
             public float skidGearLockFactor = 0.1f;// The car will not automatically change gear if the current skid factor is higher than this value.
             public float accelChangeSmoothing = 2f; // Used to smooth out changes in acceleration input.
             public float gearFactorSmoothing = 5f;// Controls the speed at which revs drop or raise to match new gear, after a gear change.
             [Range(0, 1)] public float revRangeBoundary = 0.8f; // The amount of the full rev range used in each gear.
         }
 
 
         private float[] gearDistribution;// Stores the caluclated change point for each gear (0-1 as a normalised amount relative to car's max speed)
         private Wheel[] wheels; // Stores a reference to each wheel attached to this car.
         private float accelBrake; // The acceleration or braking input (1 to -1 range)
         private float smallSpeed;// A small proportion of max speed, used to decide when to start accelerating/braking when transitioning between fwd and reverse motion
         private float maxReversingSpeed; // The maximum reversing speed
         private bool immobilized; // Whether the car is accepting inputs.
 
 
         // publicly read-only props, useful for GUI, Sound effects, etc.
         public int GearNum { get; private set; } // the current gear we're in.
         public float CurrentSpeed { get; private set; } // the current speed of the car
         public float CurrentSteerAngle { get; private set; } // The current steering angle for steerable wheels.
         public float AccelInput { get; private set; } // the current acceleration input
         public float BrakeInput { get; private set; } // the current brake input
         public float GearFactor { get; private set; }// value between 0-1 indicating where the current revs fall within the current range of revs for this gear
         public float AvgPowerWheelRpmFactor { get; private set; } // the average RPM of all wheels marked as 'powered'
         public float AvgSkid { get; private set; } // the average skid factor from all wheels
         public float RevsFactor { get; private set; }// value between 0-1 indicating where the current revs fall between 0 and max revs
         public float SpeedFactor { get; private set; }// value between 0-1 of the car's current speed relative to max speed
 
         public int NumGears
         {
             // the number of gears set up on the car
             get { return advanced.numGears; }
         }
 
 
         // the following values are provided as read-only properties,
         // and are required by the Wheel script to compute grip, burnout, skidding, etc
         public float MaxSpeed
         {
             get { return maxSpeed; }
         }
 
 
         public float MaxTorque
         {
             get { return maxTorque; }
         }
 
 
         public float BurnoutSlipEffect
         {
             get { return advanced.burnoutSlipEffect; }
         }
 
 
         public float BurnoutTendency
         {
             get { return advanced.burnoutTendency; }
         }
 
 
         public float SpinoutSlipEffect
         {
             get { return advanced.spinoutSlipEffect; }
         }
 
 
         public float SideSlideEffect
         {
             get { return advanced.sideSlideEffect; }
         }
 
 
         public float MaxSteerAngle
         {
             get { return maxSteerAngle; }
         }
 
 
         // variables added due to separating out things into functions!
         private bool anyOnGround;
         private float curvedSpeedFactor;
         private bool reversing;
         private float targetAccelInput;// target accel input is our desired acceleration input. We smooth towards it later
 
         private void Awake()
         {
             // get a reference to all wheel attached to the car.
             wheels = GetComponentsInChildren<Wheel>();
 
             SetUpGears();
 
             // deactivate and reactivate the gameobject - this is a workaround
             // to a bug where changes to wheelcolliders at runtime are not 'taken'
             // by the rigidbody unless this step is performed :(
             gameObject.SetActive(false);
             gameObject.SetActive(true);
 
             // a few useful speeds are calculated for use later:
             smallSpeed = maxSpeed*0.05f;
             maxReversingSpeed = maxSpeed*advanced.reversingSpeedFactor;
         }
 
 
         private void OnEnable()
         {
             // set adjusted centre of mass.
             GetComponent<Rigidbody>().centerOfMass = Vector3.up*adjustCentreOfMass;
         }
 
 
         public void Move(float steerInput, float accelBrakeInput)
         {
 
             // lose control of engine if immobilized
             if (immobilized) accelBrakeInput = 0;
 
             ConvertInputToAccelerationAndBraking(accelBrakeInput);
             CalculateSpeedValues();
             HandleGearChanging();
             CalculateGearFactor();
             ProcessWheels(steerInput);
             ApplyDownforce();
             CalculateRevs();
             PreserveDirectionInAir();
 
         }
 
         private void ConvertInputToAccelerationAndBraking(float accelBrakeInput)
         {
             // move.Z is the user's fwd/back input. We need to convert it into acceleration and braking.
             // this differs based on if the car is currently moving forward or backward.
             // change is based slightly away from the zero value (by "smallspeed") so that for example when
             // the car transitions from reversing to moving forwards, the car does not need to come to a complete
             // rest before starting to accelerate.
 
             reversing = false;
             if (accelBrakeInput > 0)
             {
                 if (CurrentSpeed > -smallSpeed)
                 {
                     // pressing forward while moving forward : accelerate!
                     targetAccelInput = accelBrakeInput;
                     BrakeInput = 0;
                 }
                 else
                 {
                     // pressing forward while movnig backward : brake!
                     BrakeInput = accelBrakeInput;
                     targetAccelInput = 0;
                 }
             }
             else
             {
                 if (CurrentSpeed > smallSpeed)
                 {
                     // pressing backward while moving forward : brake!
                     BrakeInput = -accelBrakeInput;
                     targetAccelInput = 0;
                 }
                 else
                 {
                     // pressing backward while moving backward : accelerate (in reverse direction)
                     BrakeInput = 0;
                     targetAccelInput = accelBrakeInput;
                     reversing = true;
                 }
             }
             // smoothly move the current accel towards the target accel value.
             AccelInput = Mathf.MoveTowards(AccelInput, targetAccelInput, Time.deltaTime*advanced.accelChangeSmoothing);
         }
 
         private void CalculateSpeedValues()
         {
             // current speed is measured in the forward direction of the car (sliding sideways doesn't count!)
             CurrentSpeed = transform.InverseTransformDirection(GetComponent<Rigidbody>().velocity).z;
             // speedfactor is a normalized representation of speed in relation to max speed:
             SpeedFactor = Mathf.InverseLerp(0, reversing ? maxReversingSpeed : maxSpeed, Mathf.Abs(CurrentSpeed));
             curvedSpeedFactor = reversing ? 0 : CurveFactor(SpeedFactor);
         }
 
         private void HandleGearChanging()
         {
             // change gear, when appropriate (if speed has risen above or below the current gear's range, as stored in the gearDistribution array)
             if (!reversing)
             {
                 if (SpeedFactor < gearDistribution[GearNum] && GearNum > 0)
                     GearNum--;
                 if (SpeedFactor > gearDistribution[GearNum + 1] && AvgSkid < advanced.skidGearLockFactor &&
                     GearNum < advanced.numGears - 1)
                     GearNum++;
             }
         }
 
         private void CalculateGearFactor()
         {
             // gear factor is a normalised representation of the current speed within the current gear's range of speeds.
             // We smooth towards the 'target' gear factor, so that revs don't instantly snap up or down when changing gear.
             var targetGearFactor = Mathf.InverseLerp(gearDistribution[GearNum], gearDistribution[GearNum + 1],
                                                      Mathf.Abs(AvgPowerWheelRpmFactor));
             GearFactor = Mathf.Lerp(GearFactor, targetGearFactor, Time.deltaTime*advanced.gearFactorSmoothing);
         }
 
         private void ProcessWheels(float steerInput)
         {
             // Process each wheel:
             // we accumulate some averages of all wheels into these vars:
             AvgPowerWheelRpmFactor = 0;
             AvgSkid = 0;
             var numPowerWheels = 0;
             anyOnGround = false;
             foreach (var wheel in wheels)
             {
                 var wheelCollider = wheel.wheelCollider;
                 if (wheel.steerable)
                 {
                     // apply steering to this wheel. The actual steering change applied is based on the steering range, current speed, 
                     // and whether the wheel is currently pointing in the direction that steering is being applied
                     var currentSteerSpeed = Mathf.Lerp(steeringResponseSpeed,
                                                        steeringResponseSpeed*maxSpeedSteerResponse, curvedSpeedFactor);
                     var currentMaxAngle = Mathf.Lerp(maxSteerAngle, maxSteerAngle*maxSpeedSteerAngle, curvedSpeedFactor);
                     // auto-correct steering to centre if no steering input:
                     if (steerInput == 0)
                     {
                         currentSteerSpeed *= advanced.steeringCorrection;
                     }
                     // increase steering speed if steering input is in opposite direction to current wheel direction (for faster response)
                     if (Mathf.Sign(steerInput) != Mathf.Sign(CurrentSteerAngle))
                     {
                         currentSteerSpeed *= advanced.oppositeLockSteeringCorrection;
                     }
                     // modify the actual steer angle of the wheel by these calculated values:
                     CurrentSteerAngle = Mathf.MoveTowards(CurrentSteerAngle, steerInput*currentMaxAngle,
                                                           Time.deltaTime*currentSteerSpeed);
                     wheelCollider.steerAngle = CurrentSteerAngle;
                 }
                 // acumulate skid amount from this wheel, for averaging later
                 AvgSkid += wheel.SkidFactor;
                 if (wheel.powered)
                 {
                     // apply power to wheels marked as powered:
                     // available torque drops off as we approach max speed
                     var currentMaxTorque = Mathf.Lerp(maxTorque, (SpeedFactor < 1) ? minTorque : 0,
                                                       reversing ? SpeedFactor : curvedSpeedFactor);
                     wheelCollider.motorTorque = AccelInput*currentMaxTorque;
                     // accumulate RPM from this wheel, for averaging later
                     AvgPowerWheelRpmFactor += wheel.Rpm/wheel.MaxRpm;
                     numPowerWheels++;
                 }
                 // apply curent brake torque to wheel
                 wheelCollider.brakeTorque = BrakeInput*brakePower;
                 // if any wheel is on the ground, the car is considered grounded
                 if (wheel.OnGround)
                 {
                     anyOnGround = true;
                 }
             }
             // average the accumulated wheel values
             AvgPowerWheelRpmFactor /= numPowerWheels;
             AvgSkid /= wheels.Length;
         }
 
         private void ApplyDownforce()
         {
             // apply downforce
             if (anyOnGround)
             {
                 GetComponent<Rigidbody>().AddForce(-transform.up*curvedSpeedFactor*advanced.downForce);
             }
         }
 
         private void CalculateRevs()
         {
             // calculate engine revs (for display / sound)
             // (this is done in retrospect - revs are not used in force/power calculations)
             var gearNumFactor = GearNum/(float) NumGears;
             var revsRangeMin = ULerp(0f, advanced.revRangeBoundary, CurveFactor(gearNumFactor));
             var revsRangeMax = ULerp(advanced.revRangeBoundary, 1f, gearNumFactor);
             RevsFactor = ULerp(revsRangeMin, revsRangeMax, GearFactor);
         }
 
         private void PreserveDirectionInAir()
         {
             // special feature which allows cars to remain roughly pointing in the direction of travel
             if (!anyOnGround && preserveDirectionWhileInAir && GetComponent<Rigidbody>().velocity.magnitude > smallSpeed)
             {
                 GetComponent<Rigidbody>().MoveRotation(Quaternion.Slerp(GetComponent<Rigidbody>().rotation, Quaternion.LookRotation(GetComponent<Rigidbody>().velocity),
                                                         Time.deltaTime));
                 GetComponent<Rigidbody>().angularVelocity = Vector3.Lerp(GetComponent<Rigidbody>().angularVelocity, Vector3.zero, Time.deltaTime);
             }
         }
 
         // simple function to add a curved bias towards 1 for a value in the 0-1 range
         private float CurveFactor(float factor)
         {
             return 1 - (1 - factor)*(1 - factor);
         }
 
 
         // unclamped version of Lerp, to allow value to exceed the from-to range
         private float ULerp(float from, float to, float value)
         {
             return (1.0f - value)*from + value*to;
         }
 
 
         private void SetUpGears()
         {
             // the gear distribution is a range of normalized values marking out where the gear changes should occur
             // over the normalized range of speeds for the car.
             // eg, if the bias is centred, 5 gears would be evenly distributed as 0-0.2, 0.2-0.4, 0.4-0.6, 0.6-0.8, 0.8-1
             // with a low bias, the gears are clumped towards the lower end of the speed range, and vice-versa for high bias.
 
             gearDistribution = new float[advanced.numGears + 1];
             for (int g = 0; g <= advanced.numGears; ++g)
             {
                 float gearPos = g/(float) advanced.numGears;
 
                 float lowBias = gearPos*gearPos*gearPos;
                 float highBias = 1 - (1 - gearPos)*(1 - gearPos)*(1 - gearPos);
 
                 if (advanced.gearDistributionBias < 0.5f)
                 {
                     gearPos = Mathf.Lerp(gearPos, lowBias, 1 - (advanced.gearDistributionBias*2));
                 }
                 else
                 {
                     gearPos = Mathf.Lerp(gearPos, highBias, (advanced.gearDistributionBias - 0.5f)*2);
                 }
 
                 gearDistribution[g] = gearPos;
             }
         }
 
 
         private void OnDrawGizmosSelected()
         {
             // visualise the adjusted centre of mass in the editor
             Gizmos.color = Color.cyan;
             Gizmos.DrawWireSphere(GetComponent<Rigidbody>().position + Vector3.up*adjustCentreOfMass, 0.2f);
         }
 
         // Immobilize can be called from other objects, if the car needs to be made uncontrollable
         // (eg, from asplosion!)
         public void Immobilize()
         {
             immobilized = true;
         }
 
         // Reset is called via the ObjectResetter script, if present.
         public void Reset()
         {
             immobilized = false;
         }
     }
 }

Comment
Add comment
10 |3000 characters needed characters left characters exceeded
â–¼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

0 Replies

· Add your reply
  • Sort: 

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

3 People are following this question.

avatar image avatar image avatar image

Related Questions

How can i check and fire an event when the user look at specific object ? 0 Answers

Adding callbacks/events to an instantiated prefab 2 Answers

How do I inherit certain varibles and functions from another script. 1 Answer

building error in my video project apk 0 Answers

How to get access to C# script in another way. 2 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges