Search Unity

Transmission for vehicle controller (CSharp)

Discussion in 'Scripting' started by Sethtek_Dev, Mar 16, 2018.

  1. Sethtek_Dev

    Sethtek_Dev

    Joined:
    Feb 4, 2017
    Posts:
    44
    Hello once again. I've been working hard on my vehicle controller, and I've been going down my list of things to do.

    I came across "Make a transmission", so I set off for a few days trying to get it to work for me.
    I found this forum, but it is in JS https://forum.unity.com/threads/manual-transmission-for-a-car.76873/
    I've converted it today, but I get a few errors and I don't entirely understand the best way to do it in C#.

    Here is the transmission snippet of my script.
    Code (CSharp):
    1. //TRANSMISSION AREA
    2.     public float MaxEngineRPM = 3000.0f;
    3.     public float MinEngineRPM = 1000.0f;
    4.     private float EngineRPM = 0.0f;
    5.     public float[] GearRatio;
    6.  
    7.     void Update ()
    8.     {
    9.         // This is to limith the maximum speed of the car, adjusting the drag probably isn't the best way of doing it,
    10.         // but it's easy, and it doesn't interfere with the physics processing.
    11.         vrb.drag = vrb.velocity.magnitude / 250;
    12.  
    13.         // Compute the engine RPM based on the average RPM of the two wheels, then call the shift gear function
    14.         EngineRPM = (driveWheels[0].rpm + driveWheels[1].rpm)/2 * GearRatio[currentGear];
    15.         ShiftGears();
    16.  
    17.         // set the audio pitch to the percentage of RPM to the maximum RPM plus one, this makes the sound play
    18.         // up to twice it's pitch, where it will suddenly drop when it switches gears.
    19.         engineSound.pitch = Mathf.Abs(EngineRPM / MaxEngineRPM) + 1.0f ;
    20.         // this line is just to ensure that the pitch does not reach a value higher than is desired.
    21.         if ( engineSound.pitch > 2.0f ) {
    22.             engineSound.pitch = 2.0f;
    23.         }
    24.  
    25.         // finally, apply the values to the wheels. The torque applied is divided by the current gear, and
    26.         // multiplied by the user input variable.
    27.         driveWheels[0].motorTorque = engineTorque / GearRatio[currentGear] * Input.GetAxis("Vertical");
    28.         driveWheels[1].motorTorque = engineTorque / GearRatio[currentGear] * Input.GetAxis("Vertical");
    29.     }
    30.  
    31.     void  ShiftGears ()
    32.     {
    33.         // this funciton shifts the gears of the vehcile, it loops through all the gears, checking which will make
    34.         // the engine RPM fall within the desired range. The gear is then set to this "appropriate" value.
    35.         if ( EngineRPM >= MaxEngineRPM ) {
    36.             int AppropriateGear = currentGear;
    37.  
    38.             for ( var i = 0; i < GearRatio.length; i ++ ) {
    39.                 if ( driveWheels[0].rpm * GearRatio[i] < MaxEngineRPM ) {
    40.                     AppropriateGear = i;
    41.                     break;
    42.                 }
    43.             }
    44.  
    45.             currentGear = AppropriateGear;
    46.         }
    47.  
    48.         if ( EngineRPM <= MinEngineRPM ) {
    49.             int AppropriateGear = currentGear;
    50.  
    51.             for ( var j = GearRatio.length-1; j >= 0; j -- ) {
    52.                 if ( driveWheels[0].rpm * GearRatio[j] > MinEngineRPM ) {
    53.                     AppropriateGear = j;
    54.                     break;
    55.                 }
    56.             }
    57.  
    58.             currentGear = AppropriateGear;
    59.         }
    60.     }
    This is the error I'm getting
    upload_2018-3-16_3-36-3.png

    Thank you for your time ;)
     
  2. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    Did you try intellisense/auto-complete? Or googling array length? :) It's with a capital 'L'.
     
  3. Sethtek_Dev

    Sethtek_Dev

    Joined:
    Feb 4, 2017
    Posts:
    44
    Yes I use them, The errors are gone now but the shifting is still not working.

    I'm still not sure why it won't shift. The current gear stays at 0 and the rpms are not even at the "lowest rpm" value.
    upload_2018-3-17_19-17-47.png

    This is my script for the vehicle controller.
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEngine.UI;
    5.  
    6. public class STKVehiclePhysics : MonoBehaviour {
    7.  
    8.     //These are the 3 main variables that control most of the vehicle functions
    9.     public float engineTorque;
    10.     public float maxSteerAngle;
    11.     public float MaxEngineRPM = 3000.0f;
    12.     public float MinEngineRPM = 1000.0f;
    13.     [SerializeField]
    14.     private float EngineRPM = 0.0f;
    15.     public int currentGear;
    16.     public float[] GearRatio;
    17.     public AudioSource engineSound;
    18.     Rigidbody vrb;
    19.  
    20.     //These are the next required variables that make the vehicle move
    21.     public Transform COM;
    22.     public WheelCollider[] steerWheels;
    23.     public WheelCollider[] driveWheels;
    24.     public bool ignition;
    25.  
    26.     //This is the output of the steering angle
    27.     public float steer;
    28.     public Transform steeringWheel;
    29.     public Vector3 steeringWheelAngles;
    30.  
    31.     //This is where the functions should be called at startup
    32.     void Start ()
    33.     {
    34.         vrb = GetComponent<Rigidbody> ();
    35.         vrb.centerOfMass = COM.localPosition;
    36.     }
    37.  
    38.     // This stuff is called once per frame
    39.     void Update ()
    40.     {
    41.         //This is the vehicle's steering
    42.         steer = Input.GetAxis("Horizontal") * maxSteerAngle;
    43.         steeringWheel.localEulerAngles = steeringWheelAngles;
    44.         steeringWheelAngles.z = - steer * 5;
    45.         //Sends the steer value to all of the steer wheels in the steerWheels array
    46.         foreach (WheelCollider wheel in steerWheels)
    47.         {
    48.             wheel.steerAngle = steer;
    49.         }
    50.  
    51.         //This is the vehicle's engine/transmission/drivetrain area
    52.         EngineRPM = (driveWheels[0].rpm + driveWheels[1].rpm)/2 * GearRatio[currentGear];
    53.  
    54.         if (Input.GetKeyDown (KeyCode.LeftShift))
    55.         {
    56.             ShiftGears ();
    57.         }
    58.  
    59.         engineSound.pitch = Mathf.Abs(EngineRPM / MaxEngineRPM) + 1.0f ;
    60.  
    61.         // this line is just to ensure that the pitch does not reach a value higher than is desired.
    62.         if ( engineSound.pitch > 2.0f )
    63.         {
    64.             engineSound.pitch = 2.0f;
    65.         }
    66.  
    67.         // finally, apply the values to the wheels. The torque applied is divided by the current gear, and
    68.         // multiplied by the user input variable.
    69.         driveWheels[0].motorTorque = engineTorque / GearRatio[currentGear] * Input.GetAxis("Vertical");
    70.         driveWheels[1].motorTorque = engineTorque / GearRatio[currentGear] * Input.GetAxis("Vertical");
    71.     }
    72.  
    73.     //TRANSMISSION AREA
    74.     void  ShiftGears ()
    75.     {
    76.         // this funciton shifts the gears of the vehicle, it loops through all the gears, checking which will make
    77.         // the engine RPM fall within the desired range. The gear is then set to this "appropriate" value.
    78.         if ( EngineRPM >= MaxEngineRPM )
    79.         {
    80.             int AppropriateGear = currentGear;
    81.  
    82.             for ( var i = 0; i < GearRatio.Length; i ++ )
    83.             {
    84.                 if ( driveWheels[0].rpm * GearRatio[i] < MaxEngineRPM )
    85.                 {
    86.                     AppropriateGear = i;
    87.                     break;
    88.                 }
    89.             }
    90.  
    91.             currentGear = AppropriateGear;
    92.         }
    93.  
    94.         if ( EngineRPM <= MinEngineRPM )
    95.         {
    96.             int AppropriateGear = currentGear;
    97.  
    98.             for ( var j = GearRatio.Length-1; j >= 0; j -- )
    99.             {
    100.                 if ( driveWheels[0].rpm * GearRatio[j] > MinEngineRPM )
    101.                 {
    102.                     AppropriateGear = j;
    103.                     break;
    104.                 }
    105.             }
    106.  
    107.             currentGear = AppropriateGear;
    108.         }
    109.     }
    110. }
    I know a little bit about arrays but this is still very confusing to me :/
    From what I'm looking at... I think the "for ( var j = GearRatio.Length-1; j >= 0; j -- )" is completely incorrect, but I have no idea how that works.

    This is the last major feature I need to add into my game. Then I can start working on other small things (like the speedometer that's based off of this.)
    :)
     
  4. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    That's just looping backwards..

    You could try putting some Debug Logs into your code to see what's/what's not happening, etc.. and try to work it out.
     
  5. Sethtek_Dev

    Sethtek_Dev

    Joined:
    Feb 4, 2017
    Posts:
    44
    I've been studying the script, but I don't really understand how the transmission part works.
    So I don't know what to log :/

    I have tried playing around with the min and max engine values, and it does shift (into fourth) but then never shifts back. It doesn't shift up through the full set of gears either.

    The engine rpm should be the same as the "min engine rpm" (I think)
    I've been searching google, but I can't find something that would work.
     
  6. danni0276

    danni0276

    Joined:
    Dec 20, 2015
    Posts:
    1
    Actually enginerpm supposed to be the same as max engine other wise its gonna think you're already maxed out and will start you in the highest gear. I tried messing with the values already. You want set the shift points a little before max. But never the minimal value.
     
  7. xVergilx

    xVergilx

    Joined:
    Dec 22, 2014
    Posts:
    3,296
    I think he's figured that out by now.
     
  8. Sethtek_Dev

    Sethtek_Dev

    Joined:
    Feb 4, 2017
    Posts:
    44
    Yes, I have figured it out.

    My new version is much better. But it still needs some major improvements eventually, which I'll be glad to work on asap :)

    Thanks for your help and suggestions guys!
     
  9. anzhonymg_unity

    anzhonymg_unity

    Joined:
    Dec 27, 2018
    Posts:
    1
    I used your code, the bad thing is that my car turns and gets up and goes back, I don't know when the speed changes, help me plis
     
  10. Bibek_Xetry

    Bibek_Xetry

    Joined:
    Jun 5, 2021
    Posts:
    2
    Why did you use mototrTorque = engine torque/ gearratios[currentgear]
     
  11. koirat

    koirat

    Joined:
    Jul 7, 2012
    Posts:
    2,074
    I guess motorTorque is final torque applied to the wheels or joint.
    Now go read how a gear transmission is working in a car and everything is going to be more obvious to you.
     
  12. Bibek_Xetry

    Bibek_Xetry

    Joined:
    Jun 5, 2021
    Posts:
    2
    @koirat I mean the greater the speed the less the torque should be used. So motorTorque = engineTorque * gearratios[current gear]. I tried it and it worked like a charm.
     
  13. augustocabrera1b

    augustocabrera1b

    Joined:
    Mar 23, 2019
    Posts:
    1
    Hey Sethtek_Dev, could you share the final script? Thank you!