【unity工程日志】写给自己看的CarControl.c#注释

【写给自己看的工作日志7.22】

虽然还是偷了一下懒,没有去105工作,但是鉴于暑假都过了一半了,而我的VR驾考项目工作还没有丝毫进展,所以,哪怕呆在宿舍也要努力学习啊!奋斗

之前的赛车手游也要找时间把工作日志补上了~主要研究了一下WheelCollider,一个很难搞的小家伙……这两天就要动手写啊!千万不要拖延症啊!!!!

这一篇博客就拿来炫耀今天工作的进展了~让一个对车没有啥印象的人来摸清楚汽车的原理……简直没话说……好难啊!!!具体的分析及涉及的知识点之后会进行补充,希望明天的进展能快一点吧……偷笑明天主要是CCar.c#以及相机相关的代码理解,加上之前红华给的的罗技盘的一些知识点。

如果可以的话,希望也能空出时间取跑个步……感觉自己越来越胖了……再见不说了,我要去操场了~得意

【PS:下面的内容是根据某个博主的思路来进行理解的……原谅我忘了到底是哪个了,所以这里就先不转载了,但还是要感谢他~】



using System;

using UnityEngine;

namespace myCar
{
    //汽车驱动类型
    internal enum CarDriveType
    {
        FrontWheelDrive,
        RearWheelDrive,
        FourWheelDrive
    }

    enum InputType
    {
      //键盘 罗技轮
      Keyboard,LogiWheel
    }

    internal enum SpeedType
    {
        MPH,//速度单位  英里
        KPH//速度单位  千米/小时
    }

    public class myCarController : MonoBehaviour
    {
        //车子为四轮驱动
        [SerializeField] private CarDriveType m_CarDriveType = CarDriveType.FourWheelDrive;
        //存放wheelcollider的数组
        [SerializeField] private WheelCollider[] m_WheelColliders = new WheelCollider[4];
        //存放车轮模型的数组
        [SerializeField] private GameObject[] m_WheelMeshes = new GameObject[4];
        //存放车轮声音、烟雾、划痕的数组
        [SerializeField] private myWheelEffects[] m_myWheelEffects = new myWheelEffects[4];
        //存放前刹的数组   
        [SerializeField] private GameObject[] m_frontBrake = new GameObject[2];  
        //车子的重心
        [SerializeField] private Vector3 m_CentreOfMassOffset;
        //最大可转角度
        [SerializeField] private float m_MaxSteerWheelAngle=360;

        [SerializeField] private float m_MaximumSteerAngle;//最大控制角
        [SerializeField] private float m_MinimumSteerAngle;//最小控制角
        [Range(0, 1)] [SerializeField] private float m_SteerHelper; //初始化为0,1是车被控制面对的方向 0 is raw physics , 1 the car will grip in the direction it is facing
        [Range(0, 1)] [SerializeField] private float m_TractionControl; //0没有牵引力控制系统,1是完整的干扰0 is no traction control, 1 is full interference
       
        //所有车轮的扭矩  扭矩越大,加速性能越好;扭矩越小,加速性能越差
        //如某车的1挡齿比(齿轮的齿数比,本质就是齿轮的半径比)是3,尾牙为4,轮胎半径为0.3米,原扭矩是200Nm的话,最后在轮轴的扭矩就变成200×3×4=2400Nm,再除以轮胎半径0.3米后,轮胎与地面摩擦的部分就有2400Nm/0.3m=8000N,即800公斤力的驱动力,这就足以驱动汽车了
        [SerializeField] private float m_FullTorqueOverAllWheels;
        //没用到???反向扭矩
        [SerializeField] private float m_ReverseTorque;
        //最大手刹扭矩
        [SerializeField] private float m_MaxHandbrakeTorque;
        //最大下压力:在中高速行驶时可以产生作用在车上向下的压力,随著速度的增加下压力可以几何级增长。下压力的提升可以增大车辆的抓地力,由此可以具有更好的操纵性
        [SerializeField] private float m_Downforce = 100f;
        //速度类型
        [SerializeField] private SpeedType m_SpeedType;
        //最大速度
        [SerializeField] private float m_Topspeed = 200;
        //??最大倒车速度??
        [SerializeField] private float m_TopBackspeed = 10;
        //??转速范围边界??
        [SerializeField] private float m_RevRangeBoundary = 1f;
        //滑动极限
        [SerializeField] private float m_SlipLimit;
        //制动力矩/刹车扭矩
        [SerializeField] private float m_BrakeTorque;
        //键盘控制
        [SerializeField] private InputType inputType = InputType.Keyboard;
        
        //??????有待考证
        public bool shifter = false;//移动装置
        public bool needClutch = false;//是否需要离合器
        public bool autoGear= false;//自动换挡
        public string shiftUpButton="ShiftUp";//升档按钮
        public string shiftDownButton="ShiftDown";//降档按钮
        private float old_wheelangle;//之前的轮角
        public GameObject wheel;//方向盘
        public int wheelz = 57;
        public int wheely = 23;

        
        public int GearsNum = 7;//档数
        public int positiveGearsNum = 5;//档位因子
        public int m_GearNum;//当前档数
        public bool pressHandbrake;
        private bool autoClutchUp = false;//离合器上去
        private bool autoClutchDown = false;//离合器下来
        private int tickTime = 0;
        private bool ispress = false;
        private Quaternion[] m_WheelMeshLocalRotations;
        private Vector3 m_Prevpos, m_Pos;
        private float m_SteerAngle;
        private float m_GearFactor;
        private float m_OldRotation;
        private float m_CurrentTorque;
        private Rigidbody m_Rigidbody;
        private const float k_ReversingThreshold = 0.01f;
        private float[] angle=new float[2];
        private float[] old_steerAngle=new float[2];

        public GameObject[] panelShowArray;//面板显示数组
        public TextMesh[] panelNumArray;//仪盘表档位显示
        private float oldSpeedPanelAngle=0;    //角度329~575
        private float oldSpeedFactorPanelAngle = 0;
        private float CurrentTorque;
        float hshow;
        float handbrakeshow;
        float vshow;
        float brakeshow;

        public float AccelInput { get; private set; }
        public float BrakeInput { get; private set; }
        public bool Skidding { get; private set; }
        public float CurrentSteerAngle{ get { return m_SteerAngle; }}
        public float CurrentSpeed{ get { return m_Rigidbody.velocity.magnitude*2.23693629f; }}//返回了刚体的速度
        public float MaxSpeed{get { return m_Topspeed; }}//返回最大速度
        public float Revs { get; private set; }

        public float everyGearlimit_factor;

        public float PlusTorque;

        [Range(0f, 1f)]
        public float factor;
        [Range(0f, 1f)]
        public float speedfactor;

        public float[] myGearFactor;

        [Range(-1f, 1f)]
        public float[] myAccelSpeedFactor;

        //float testtoque = 500;
        //float oldrpm = 0;
        //float time = 0;

        // Use this for initialization
        private void Start()
        {
            m_WheelMeshLocalRotations = new Quaternion[4];//四个轮胎的自转方向:四元数来表示车轮方向,http://blog.csdn.net/soilwork/article/details/1447346
            for (int i = 0; i < 4; i++)
            {
                m_WheelMeshLocalRotations[i] = m_WheelMeshes[i].transform.localRotation;//当前车轮的角度
            }
            m_WheelColliders[0].attachedRigidbody.centerOfMass = m_CentreOfMassOffset;//车子的质心放在wheelcollider[0]的质心位置
            //手刹初始值为最大
            m_MaxHandbrakeTorque = float.MaxValue;
            //获取刚体组件
            m_Rigidbody = GetComponent<Rigidbody>();
            //当前扭矩=全部扭矩-(牵引系数【0-1】*全部扭矩)
            //设置当前扭矩,初始化的扭矩值跟m_TractionControl大小有关,m_TractionControl决定是否有牵引力,如果m_TractionControl
            //值为0,则当前扭矩直接就是最大值,如果该值为1,则初始扭矩为0,然后汽车启动慢慢增加扭矩力。建议m_TractionControl数值为0.5
            m_CurrentTorque = m_FullTorqueOverAllWheels - (m_TractionControl*m_FullTorqueOverAllWheels);
            
        }

        // 一个简单的函数来添加一个偏向1的曲线 【0 - 1的值的范围内】simple function to add a curved bias towards 1 for a value in the 0-1 range
        private static float CurveFactor(float factor)
        {
            return 1 - (1 - factor)*(1 - factor);
        }


        // 松开插值的版本,允许值超出范围unclamped version of Lerp, to allow value to exceed the from-to range
        //非限制版本的插值函数,“非限制”怎么体现?
        private static float ULerp(float from, float to, float value)
        {
            return (1.0f - value)*from + value*to;
        }

       //计算齿轮因素/档位因子
        private void CalculateGearFactor()
        {
            float f = (1/(float) GearsNum);
            // 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.
            //齿轮因素是在当前齿轮的速度范围的正常表示。我们顺利走向“目标”装备因素,所以转速时不要立即调节或向下改变齿轮。
            //目标齿轮数=(当前速度/最大速度)*最大齿轮数-当前齿轮数
            //我们要让值平滑地想着目标移动,以保证转速不会在变换档位时突然地上高或者降低
            //反向差值,通过当前速度的比例值,找当前速度在当前档位的比例位置,得到的值将是一个0~1范围内的值。
            var targetGearFactor = Mathf.InverseLerp(f*m_GearNum, f*(m_GearNum + 1), Mathf.Abs(CurrentSpeed/MaxSpeed));//反插值,计算比例值(5,10,8)=(8-5)/(10-5)=3/5  mathf.abs绝对值
            //从当前档位因子向目标档位因子做平滑差值
            m_GearFactor = Mathf.Lerp(m_GearFactor, targetGearFactor, Time.deltaTime*5f);
        }

        //计算引擎转速(显示/声音)
        private void CalculateRevs()
        {   //计算引擎转速(显示/声音)
            //(这样做是回想起来-转速不习惯在力/功率计算)
            //(我的个人理解:)这个计算是回溯的转速,不能用于力的计算。
            //计算在当前档位上的转速因子(决定在当前档位上的转速)
            // calculate engine revs (for display / sound)
            // (this is done in retrospect - revs are not used in force/power calculations)
            CalculateGearFactor();
            var gearNumFactor = m_GearNum/(float) GearsNum;
            //计算当前档位最小速度
            var revsRangeMin = ULerp(0f, m_RevRangeBoundary, CurveFactor(gearNumFactor));
            //计算当前档位最大速度
            var revsRangeMax = ULerp(m_RevRangeBoundary, 1f, gearNumFactor);
            //根据当前的转速因子,计算当前的转速
            Revs = ULerp(revsRangeMin, revsRangeMax, m_GearFactor);
        }


        public void Move(float steering, float accel, float footbrake, float clutch, float handbrake)
        {
            for (int i = 0; i < 4; i++)
            {
                Quaternion quat;
                Vector3 position;
                m_WheelColliders[i].GetWorldPose(out position, out quat);
                m_WheelMeshes[i].transform.position = position;
                m_WheelMeshes[i].transform.rotation = quat;
            }

            //steering wheel 控制方向盘的旋转
            wheel.transform.Rotate(new Vector3(0, -wheelz, wheely), steering * m_MaxSteerWheelAngle - old_wheelangle * m_MaxSteerWheelAngle);
            old_wheelangle = steering;
            //panelShowArray面板显示数组  CurrentSpeed返回了刚体的速度
            panelShowArray[0].transform.Rotate(new Vector3(0, 1, 0), (CurrentSpeed - oldSpeedPanelAngle) * 242.0f / 150.0f, Space.Self);//Space.Self指局部坐标,即绕Y轴转动
            oldSpeedPanelAngle = CurrentSpeed;
            float factor = CurrentTorque / m_CurrentTorque;
            if(speedfactor>0)
            {
                panelShowArray[1].transform.Rotate(new Vector3(0, 1, 0), (Mathf.Clamp(speedfactor,0f,1f) - oldSpeedFactorPanelAngle) * 240f, Space.Self);
                oldSpeedFactorPanelAngle = Mathf.Clamp(speedfactor, 0f, 1f);
            }

            float showSpeed = (int)CurrentSpeed;
            if (CurrentSpeed % ((int)CurrentSpeed) > 0.5f)
                showSpeed++;
            
            //面板上显示当前档位
            panelNumArray[0].text = ""+showSpeed;
            if (m_GearNum == -1)
                panelNumArray[1].text = "" + "R";
            else if (m_GearNum == 0)
                panelNumArray[1].text = "" + "H";
            else
            {
                panelNumArray[1].text = "" + m_GearNum;
            }
           
            //限定输入值范围clamp input values
            steering = Mathf.Clamp(steering, -1, 1);
            AccelInput= accel = Mathf.Clamp(accel, 0, 1);

            if (autoGear)
                needClutch = true;
               if(inputType==InputType.Keyboard)
               {
                   BrakeInput = footbrake = -1 * Mathf.Clamp(footbrake, -1, 0);
                   if (needClutch)
                       clutch = -1 * Mathf.Clamp(clutch, -1, 0);
                   else
                       clutch = 0;
               }
                else
               {
                   BrakeInput = footbrake = (footbrake + 1) * 0.5f;
                   if (needClutch)
                       clutch = (clutch + 1) * 0.5f;
                   else
                       clutch = 0;
               }

            //设置前轮转角
            //wheels下标为0、1的就是前轮
            //Set the steer on the front wheels.
            //Assuming that wheels 0 and 1 are the front wheels.
            m_SteerAngle = steering *m_MaximumSteerAngle;
            m_WheelColliders[0].steerAngle = m_SteerAngle;
            m_WheelColliders[1].steerAngle = m_SteerAngle;
            //换挡
            GearChange(clutch);
            //角度辅助助手,旋转更平滑
            SteerHelper();
            //设置加速/刹车信息到WheelCollider
            ApplyDrive(accel, footbrake,clutch,(int)handbrake);
            //检查速度范围
            CapSpeed();

            //Set the handbrake.
            //Assuming that wheels 2 and 3 are the rear wheels.
            //计算转速
            CalculateRevs();
            //施加下压力
            AddDownForce();
            //检查轮胎
            CheckForWheelSpin();
            //牵引力控制系统
            TractionControl();

            //show
            hshow = m_SteerAngle;
            vshow =footbrake ;
            brakeshow = accel;
            handbrakeshow =handbrake;

        }

//控制车速
        private void CapSpeed()
        {
            float speed = m_Rigidbody.velocity.magnitude;
            switch (m_SpeedType)
            {
                case SpeedType.MPH:
                    //转换单位便于比较,将速度m/s转换为mile/h
                    speed *= 2.23693629f;
                    if (speed > m_Topspeed)
                        m_Rigidbody.velocity = (m_Topspeed/2.23693629f) * m_Rigidbody.velocity.normalized;
                    break;
                //将速度m/s转换为km/h,以便比较
                case SpeedType.KPH:
                    speed *= 3.6f;
                    if (speed > m_Topspeed)
                        m_Rigidbody.velocity = (m_Topspeed/3.6f) * m_Rigidbody.velocity.normalized;
                    break;
            }
        }

//设置加速/刹车信息到WheelCollider
        private void ApplyDrive(float accel, float footbrake,float clutch,int handbrake)
        {
            if (handbrake == 1&&!ispress)
            {
                pressHandbrake = !pressHandbrake;
                ispress = true;
            }
            if (handbrake == 0)
                ispress = false;
         

            float thrustTorque;


            switch (m_CarDriveType)
            {
                case CarDriveType.FourWheelDrive:
                    thrustTorque =accel * (m_CurrentTorque / 4f);                   
                    for (int i = 0; i < 4; i++)
                        myApplyDrive(i,thrustTorque,clutch);
                    break;

                case CarDriveType.FrontWheelDrive:
                    thrustTorque = accel * (m_CurrentTorque / 2f);
                    myApplyDrive(0, thrustTorque, clutch);
                    myApplyDrive(1, thrustTorque, clutch);
                    break;

                case CarDriveType.RearWheelDrive:
                    thrustTorque = accel * (m_CurrentTorque / 2f);
                //    thrustTorque = testtoque;
                //    if(testtoque>=164.4948)
                //    testtoque-=0.1f;
                    
                //    Debug.Log(CurrentSpeed+"eee"+testtoque);
                //oldrpm = CurrentSpeed;
                    myApplyDrive(2, thrustTorque, clutch);
                    myApplyDrive(3, thrustTorque, clutch);
                    break;

            }

            for (int i = 0; i < 4; i++)
            {
                

                if (!pressHandbrake)
               {
                   if (Vector3.Angle(transform.forward, m_Rigidbody.velocity) < 50f && CurrentSpeed > m_TopBackspeed)
                       m_WheelColliders[i].brakeTorque = m_BrakeTorque * accel;
                   else if (footbrake > 0)
                   {
                       //m_WheelColliders[i].brakeTorque = m_ReverseTorque * footbrake;
                       if(CurrentSpeed>10)
                           m_WheelColliders[i].brakeTorque = m_BrakeTorque * footbrake;
                       else
                       m_WheelColliders[i].motorTorque = 100 * footbrake;
                   }
                   else
                   {
                       m_WheelColliders[i].brakeTorque = 0;
                       WheelHit wh;
                       m_WheelColliders[i].GetGroundHit(out wh);
                       float groundangle = Vector3.Angle(Vector3.up, wh.normal);
                       if (groundangle > 5 && accel == 0 && CurrentSpeed < 1)
                           m_WheelColliders[i].motorTorque = 1;
                   }
               }
                else
                    m_WheelColliders[i].brakeTorque = m_MaxHandbrakeTorque;//刹车的力矩。这个值必须为正。
            }
      
     
        }
       
//挂挡【档位更新】
        void GearChange(float clutch)
        {//不是自动挡
           if(!autoGear)
           {
              if(needClutch)
              {//踩离合换挡
                 if(clutch>0.5f)
                     Gear();
              }
               else
              {//不需要离合直接换挡
                  Gear();
              }
           }
           
           //自动换挡
            else
           {
               //后退档
               if (Input.GetButton("reverse")||Input.GetButtonDown(shiftDownButton))
                   m_GearNum = -1;
               //空挡
               else if (Input.GetButton("neutral"))
                   m_GearNum = 0;
               //1档
               else if (Input.GetButtonDown("first") || Input.GetButtonDown(shiftUpButton))
                   m_GearNum = 1;
               //运行时汽车自动换挡
               //这里其实相当于将所有速度进行了划分,f就是指的目前速度处于最大速度的几分之几
               //如果NoOfGears是5,那么就把速度分成5段
               //1档就是0/5 ~ 1/5,
               //2档就是1/5 ~ 2/5,
               //3档就是2/5 ~ 3/5,
               //4档就是3/5 ~ 4/5,
               //5档就是4/5 ~ 5/5,
               //每次先看当前档位是几档,然后看当前速度是否匹配当前档位,如果匹配当前档位没啥事,如果不匹配则看当前速度如果小于当前档位
               //最小速度则减档,如果大于当前档位最大速度则,加档;
               else if(m_GearNum>0&&m_GearNum<=positiveGearsNum)
               {
                   float f = Mathf.Abs(CurrentSpeed / MaxSpeed);
                   //计算当前档位速度下限
                   float downgearlimit = (1 / (float)positiveGearsNum) * (m_GearNum-1) ;
                   //计算当前档位速度上限
                   float upgearlimit = (1 / (float)positiveGearsNum) * (m_GearNum);

                   factor = 1.2f - (float)m_GearNum / positiveGearsNum;
                   speedfactor = f / upgearlimit;

                  if(!autoClutchDown&&tickTime==0)
                  {
                      if (f > upgearlimit && m_GearNum < positiveGearsNum)
                          autoClutchUp = true;
                  }

                  if(!autoClutchUp&&tickTime==0)
                  {
                      if (m_GearNum > 1 && f < downgearlimit)
                          autoClutchDown = true;
                  }

                  if (autoClutchUp && tickTime == 0)
                   {
                       m_GearNum++;
                       tickTime++;
                   }
                  if (autoClutchDown && tickTime == 0)
                   {
                       m_GearNum--;
                       tickTime++;
                   }

                 if(tickTime!=0)
                 {
                     tickTime++;
                     if (tickTime > 10)
                     {
                         tickTime = 0;
                         autoClutchDown = false;
                         autoClutchUp = false;
                     }
                 }

               }
               else
                   speedfactor = CurrentSpeed / m_TopBackspeed;
            }
        }

//手动切换当前档位
        void Gear()
        {   //根据键盘来更换当前档位
            if (shifter == true && inputType != InputType.Keyboard)
            {
                if (Input.GetButton("reverse"))
                    m_GearNum = -1;
                else if (Input.GetButton("neutral"))
                    m_GearNum = 0;
                else if (Input.GetButton("first"))
                    m_GearNum = 1;
                else if (Input.GetButton("second"))
                    m_GearNum = 2;
                else if (Input.GetButton("third"))
                    m_GearNum = 3;
                else if (Input.GetButton("fourth"))
                    m_GearNum = 4;
                else if (Input.GetButton("fifth"))
                    m_GearNum = 5;
                else if (Input.GetButton("sixth"))
                    m_GearNum = -1;
                else
                    m_GearNum = 0;
            }
            else
            {//方向键控制
                if (Input.GetButtonDown(shiftUpButton))
                {
                    if (m_GearNum < positiveGearsNum)
                        m_GearNum++;
                }
                if (Input.GetButtonDown(shiftDownButton))
                {
                    if (m_GearNum > -1)
                        --m_GearNum;
                }
            }
        }

        void myApplyDrive(int i,float oneTorque,float clutch)
        {
            CurrentTorque = oneTorque;
         if(!pressHandbrake)
         {
             if (!autoGear)
             {
                 if (m_GearNum > 0)
                 {
                     float f = Mathf.Abs(CurrentSpeed / MaxSpeed);
                     float upgearlimit = (1 / (float)positiveGearsNum) * m_GearNum * GetFactor(myGearFactor);
                     float downgearlimit = (1 / (float)positiveGearsNum) * m_GearNum;
                     float IForNOT;
                     if (f >= downgearlimit)
                         IForNOT = 1;
                     else
                         IForNOT = 0;

                     float calTorque;
                     factor = 1.2f - (float)m_GearNum / positiveGearsNum;
                     speedfactor = f / upgearlimit;
                     calTorque = factor * oneTorque + (1.2f - factor) * oneTorque * (CurrentSpeed / MaxSpeed) + PlusTorque * GetFactor(myAccelSpeedFactor) * IForNOT;
                     if (f > upgearlimit)
                         calTorque = everyGearlimit_factor * calTorque;
                     m_WheelColliders[i].motorTorque = -calTorque * (1 - clutch);
                     CurrentTorque = calTorque;
                 }
                 else if (m_GearNum < 0 && CurrentSpeed < m_TopBackspeed)
                 {
                     m_WheelColliders[i].motorTorque = oneTorque * (1 - clutch);
                     speedfactor = CurrentSpeed / m_TopBackspeed;
                 }
                 else
                     speedfactor = CurrentSpeed / m_TopBackspeed;
             }
             else
             {
                 if(m_GearNum>0)
                     m_WheelColliders[i].motorTorque = -oneTorque;
                 else
                     m_WheelColliders[i].motorTorque = oneTorque;
             }
         }

        }
   
        float GetFactor(float[] fact)
        {
            if (myGearFactor.Length != positiveGearsNum)
            {
                Debug.LogError("GearFactor Error!");
                return -1;
            }
            else
                return fact[m_GearNum-1];

        }

        private void SteerHelper()
        {
            for (int i = 0; i < 4; i++)
            {
                WheelHit wheelhit;
                m_WheelColliders[i].GetGroundHit(out wheelhit);
                if (wheelhit.normal == Vector3.zero)
                    return; // wheels arent on the ground so dont realign the rigidbody velocity
                //假如轮子离地,就不用调整汽车角度了
            }

            // this if is needed to avoid gimbal lock problems that will make the car suddenly shift direction
            //这个是为了避免万向锁问题的,万向锁问题会导致汽车突然变换方向(我直到万向锁问题,但不理解下面是怎么避免问题的,我只知道四元数的使用
            //就是为了避免万向锁问题)
            //下面这个If函数的效果就是,假如上一次车体Y方向角度比这次小于十度,就根据相差的度数乘以系数m_SteerHelper
            //计算出这个偏移角度的四元数,然后将刚体速度直接旋转这个偏倚度数,
            //根据代码开头m_SteerHelper的定义,这个做法相当于做了一个角度辅助,不完全凭借WheelCollider物理效果
            //而直接操控速度方向,对车角度进行调整。
            if (Mathf.Abs(m_OldRotation - transform.eulerAngles.y) < 10f)
            {
                var turnadjust = (transform.eulerAngles.y - m_OldRotation) * m_SteerHelper;
                Quaternion velRotation = Quaternion.AngleAxis(turnadjust, Vector3.up);
                m_Rigidbody.velocity = velRotation * m_Rigidbody.velocity;
            }
            m_OldRotation = transform.eulerAngles.y;

            for(int i=0;i<m_frontBrake.Length;i++)
            {
                angle[i] = m_SteerAngle - old_steerAngle[i];
                old_steerAngle[i] = m_SteerAngle;
                m_frontBrake[i].transform.RotateAround(m_WheelMeshes[i].transform.position, Vector3.up, angle[i]);
            }
        }


// 添加下压力:这是用来添加更多的速度控制this is used to add more grip in relation to speed
        private void AddDownForce()
        {
            m_WheelColliders[0].attachedRigidbody.AddForce(-transform.up*m_Downforce*
                                                         m_WheelColliders[0].attachedRigidbody.velocity.magnitude);
        }


       // checks if the wheels are spinning and is so does three things
        //检查轮胎是否旋转
        // 1) emits particles
        //检查是否发射尾气粒子
        // 2) plays tiure skidding sounds
        //播放滑行音
        // 3) leaves skidmarks on the ground
        //去掉刹车印
        // these effects are controlled through the WheelEffects class
        //这些特效都是通过WheelEffects类控制的
//检查轮胎
        private void CheckForWheelSpin()
        {
            // loop through all wheels
            for (int i = 0; i < 4; i++)
            {
                WheelHit wheelHit;
                m_WheelColliders[i].GetGroundHit(out wheelHit);

                // 轮胎下滑超过给定的阈值吗 is the tire slipping above the given threshhold
                if (Mathf.Abs(wheelHit.forwardSlip) >= m_SlipLimit || Mathf.Abs(wheelHit.sidewaysSlip) >= m_SlipLimit)
                {
                    m_myWheelEffects[i].EmitTyreSmoke();
                    //超出则发射烟雾粒子
                    // avoiding all four tires screeching at the same time
                    // if they do it can lead to some strange audio artefacts
                    //避免四个轮胎都同时播放滑行声音
                    //如果那样的话会导致某些奇怪的音效
                    if (!AnySkidSoundPlaying())
                    {
                        m_myWheelEffects[i].PlayAudio();
                    }
                    continue;
                }

                // if it wasnt slipping stop all the audio
                //假如没有超出阈值,还没有停止音效,则停止音效
                if (m_myWheelEffects[i].PlayingAudio)
                {
                    m_myWheelEffects[i].StopAudio();
                }
                // end the trail generation
                //停止烟雾生成
                m_myWheelEffects[i].EndSkidTrail();
            }
        }

        // crude traction control that reduces the power to wheel if the car is wheel spinning too much
        //如果汽车轮胎过度滑转,牵引力系统可以控制减少轮胎动力
//牵引力控制系统
        private void TractionControl()
        {
            WheelHit wheelHit;
            switch (m_CarDriveType)
            {
                case CarDriveType.FourWheelDrive:
                    // loop through all wheels
                    for (int i = 0; i < 4; i++)
                    {
                        m_WheelColliders[i].GetGroundHit(out wheelHit);
                        AdjustTorque(wheelHit.forwardSlip);
                    }
                    break;

                case CarDriveType.RearWheelDrive:
                    m_WheelColliders[2].GetGroundHit(out wheelHit);
                    AdjustTorque(wheelHit.forwardSlip);

                    m_WheelColliders[3].GetGroundHit(out wheelHit);
                    AdjustTorque(wheelHit.forwardSlip);
                    break;

                case CarDriveType.FrontWheelDrive:
                    m_WheelColliders[0].GetGroundHit(out wheelHit);
                    AdjustTorque(wheelHit.forwardSlip);

                    m_WheelColliders[1].GetGroundHit(out wheelHit);
                    AdjustTorque(wheelHit.forwardSlip);
                    break;
            }
        }


        private void AdjustTorque(float forwardSlip)
        {//当向前滑动距离超过阈值后,就说明轮胎过度滑转,则减少牵引力,以降低转速。
            //调整m_CurrentTorque值的大小来控制牵引力
            if (forwardSlip >= m_SlipLimit && m_CurrentTorque >= 0)
            {
                m_CurrentTorque -= 10 * m_TractionControl;
            }
            else
            {
                m_CurrentTorque += 10 * m_TractionControl;
                if (m_CurrentTorque > m_FullTorqueOverAllWheels)
                {
                    m_CurrentTorque = m_FullTorqueOverAllWheels;
                }
            }
        }


        void OnGUI()
        {
          GUIStyle size=new GUIStyle();
          size.fontSize=30;
            GUI.Label(new Rect(500, 20, 100, 20), "Throttle:" + vshow);
            GUI.Label(new Rect(500, 50, 100, 20), "Wheel:" + hshow);
            GUI.Label(new Rect(500, 70, 100, 20), "Brake:" + brakeshow);
            GUI.Label(new Rect(500, 90, 100, 20), "handBrake:" + handbrakeshow);
            GUI.Label(new Rect(500, 120, 100, 20), "geer:" + m_GearNum, size);
            GUI.Label(new Rect(500, 160, 100, 20), "speed:" + (int)CurrentSpeed, size);
        }

        private bool AnySkidSoundPlaying()
        {
            for (int i = 0; i < 4; i++)
            {
                if (m_myWheelEffects[i].PlayingAudio)
                {
                    return true;
                }
            }
            return false;
        }
    }
}


  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值