unity官方资源包CarController理解


    最近要写汽车的控制,发现比人物控制难很多,涉及到汽车的很多知识,自己写了一点不忍直视,各种bug,然后被告知untiy官方资源包里有控制脚本,就去学习了一下,然后借鉴了网上的一些教程,在这里表示衷心感谢,为了方面自己和他人,免得自己弄丢,然后贴在这里:

[csharp] view plain copy
  1. using System;  
  2. using UnityEngine;  
  3.   
  4. namespace UnityStandardAssets.Vehicles.Car//此处可改成自己的car名字  
  5. {  
  6.     internal enum CarDriveType  
  7.     {  
  8.         FrontWheelDrive,//前驱  
  9.         RearWheelDrive,//后驱  
  10.         FourWheelDrive//四驱  
  11.     }  
  12.   
  13.     internal enum SpeedType  
  14.     {  
  15.         MPH,//英里  
  16.         KPH//千米/h  
  17.     }  
  18.   
  19.     public class CarController : MonoBehaviour  
  20.     {  
  21.         //[SerializeField]是为了成员变量可以在检视面板上显示  
  22.         [SerializeField] private CarDriveType m_CarDriveType = CarDriveType.FourWheelDrive; //四驱  
  23.         [SerializeField] private WheelCollider[] m_WheelColliders = new WheelCollider[4]; //存放轮子的数组  
  24.         [SerializeField] private GameObject[] m_WheelMeshes = new GameObject[4]; //车轮模型  
  25.         [SerializeField] private WheelEffects[] m_WheelEffects = new WheelEffects[4];//存放特效数组,粒子,音效等  
  26.         [SerializeField] private Vector3 m_CentreOfMassOffset;//车的重心  
  27.         [SerializeField] private float m_MaximumSteerAngle;//最大可转角度  
  28.         [Range(0, 1)] [SerializeField] private float m_SteerHelper; // 0 is raw physics , 1 the car will grip in the direction it is facing//初始化为0,1是车被控制面对的方向  
  29.         [Range(0, 1)] [SerializeField] private float m_TractionControl; // 0 is no traction control, 1 is full interference///0没有牵引力控制系统,1是完整的干扰  
  30.      //所有车轮的扭矩  扭矩越大,加速性能越好;扭矩越小,加速性能越差  
  31.      //如某车的1挡齿比(齿轮的齿数比,本质就是齿轮的半径比)是3,尾牙为4,轮胎半径为0.3米,原扭矩是200Nm的话,最后在轮轴的扭矩就变成200×3×4=2400Nm,  
  32.      //再除以轮胎半径0.3米后,轮胎与地面摩擦的部分就有2400Nm/0.3m=8000N,即800公斤力的驱动力,这就足以驱动汽车了  
  33.   
  34.         //驱动力公式:驱动力=扭矩×变速箱齿比×主减速器速比×机械效率÷轮胎半径  
  35.         [SerializeField] private float m_FullTorqueOverAllWheels;//所有轮胎的扭矩  
  36.         [SerializeField] private float m_ReverseTorque;//反向扭矩  
  37.         [SerializeField] private float m_MaxHandbrakeTorque;//最大刹车扭矩  
  38.         [SerializeField] private float m_Downforce = 100f;//下压力  
  39.         [SerializeField] private SpeedType m_SpeedType;//速度类型  
  40.         [SerializeField] private float m_Topspeed = 200;//最大速度  
  41.         [SerializeField] private static int NoOfGears = 5;//档位数  
  42.         [SerializeField] private float m_RevRangeBoundary = 1f;//最大滑动距离  
  43.         [SerializeField] private float m_SlipLimit;//轮胎下滑给定的阈值  
  44.         [SerializeField] private float m_BrakeTorque;//刹车扭矩  
  45.   
  46.         private Quaternion[] m_WheelMeshLocalRotations;//四元数组存储车轮本地转动数据  
  47.         private Vector3 m_Prevpos, m_Pos;  
  48.         private float m_SteerAngle; //转向角  
  49.         private int m_GearNum;//档位数  
  50.         private float m_GearFactor;//挡位因子  
  51.         private float m_OldRotation;//用于转动计算  
  52.         private float m_CurrentTorque;//当前扭矩  
  53.         private Rigidbody m_Rigidbody;//刚体  
  54.         private const float k_ReversingThreshold = 0.01f; //反转阈值  
  55.   
  56.         //角色信息访问控制,对外接口  
  57.         public bool Skidding { getprivate set; }  
  58.         public float BrakeInput { getprivate set; }  
  59.         public float CurrentSteerAngle{ get { return m_SteerAngle; }}//当前车轮角度  
  60.         public float CurrentSpeed{ get { return m_Rigidbody.velocity.magnitude*2.23693629f; }}//当前速度  
  61.         public float MaxSpeed{get { return m_Topspeed; }}//最大速度  
  62.         public float Revs { getprivate set; }//转速属性  
  63.         public float AccelInput { getprivate set; } //加速输入  
  64.   
  65.         // Use this for initialization  
  66.         //初始化  
  67.         private void Start()  
  68.         {  
  69.             m_WheelMeshLocalRotations = new Quaternion[4]; //获得车轮的四元数的角度信息  
  70.             for (int i = 0; i < 4; i++)  
  71.             {  
  72.                 m_WheelMeshLocalRotations[i] = m_WheelMeshes[i].transform.localRotation;  
  73.             }  
  74.             m_WheelColliders[0].attachedRigidbody.centerOfMass = m_CentreOfMassOffset;  
  75.   
  76.             m_MaxHandbrakeTorque = float.MaxValue;  
  77.   
  78.             m_Rigidbody = GetComponent<Rigidbody>();  
  79.   
  80.             //当前扭矩=全部扭矩-(牵引系数【0-1】*全部扭矩)  
  81.             //设置当前扭矩,初始化的扭矩值跟m_TractionControl大小有关,m_TractionControl决定是否有牵引力,如果m_TractionControl  
  82.             //值为0,则当前扭矩直接就是最大值,如果该值为1,则初始扭矩为0,然后汽车启动慢慢增加扭矩力。建议m_TractionControl数值为0.5  
  83.             m_CurrentTorque = m_FullTorqueOverAllWheels - (m_TractionControl*m_FullTorqueOverAllWheels);//  
  84.         }  
  85.   
  86.         //变档函数  
  87.         private void GearChanging()  
  88.         {  
  89.             float f = Mathf.Abs(CurrentSpeed/MaxSpeed);  
  90.             float upgearlimit = (1/(float) NoOfGears)*(m_GearNum + 1);  
  91.             float downgearlimit = (1/(float) NoOfGears)*m_GearNum;  
  92.   
  93.             if (m_GearNum > 0 && f < downgearlimit)  
  94.             {  
  95.                 m_GearNum--;  
  96.             }  
  97.   
  98.             if (f > upgearlimit && (m_GearNum < (NoOfGears - 1)))  
  99.             {  
  100.                 m_GearNum++;  
  101.             }  
  102.         }  
  103.   
  104.         //在0-1范围内为值添加一个曲线偏向1的简单函数  
  105.         // simple function to add a curved bias towards 1 for a value in the 0-1 range  
  106.         private static float CurveFactor(float factor)  
  107.         {  
  108.             return 1 - (1 - factor)*(1 - factor);  
  109.         }  
  110.   
  111.         //松开插值的版本,允许值超出范围  
  112.         // unclamped version of Lerp, to allow value to exceed the from-to range  
  113.         private static float ULerp(float from, float to, float value)  
  114.         {  
  115.             return (1.0f - value)*from + value*to;  
  116.         }  
  117.   
  118.         //计算齿轮因素/档位因子  
  119.         private void CalculateGearFactor()  
  120.         {  
  121.             float f = (1/(float) NoOfGears);  
  122.             // gear factor is a normalised representation of the current speed within the current gear's range of speeds.  
  123.             // We smooth towards the 'target' gear factor, so that revs don't instantly snap up or down when changing gear.  
  124.             //齿轮因素是在当前齿轮的速度范围的正常表示。我们顺利走向“目标”装备因素,所以转速时不要立即调节或向下改变齿轮。  
  125.             //目标齿轮数=(当前速度/最大速度)*最大齿轮数-当前齿轮数  
  126.             //我们要让值平滑地想着目标移动,以保证转速不会在变换档位时突然地上高或者降低  
  127.             //反向差值,通过当前速度的比例值,找当前速度在当前档位的比例位置,得到的值将是一个0~1范围内的值。  
  128.             var targetGearFactor = Mathf.InverseLerp(f*m_GearNum, f*(m_GearNum + 1), Mathf.Abs(CurrentSpeed/MaxSpeed));//反插值,计算比例值(5,10,8)=(8-5)/(10-5)=3/5  
  129.             m_GearFactor = Mathf.Lerp(m_GearFactor, targetGearFactor, Time.deltaTime*5f);   //从当前档位因子向目标档位因子做平滑差值  
  130.         }  
  131.   
  132.         //计算引擎转速(显示/声音)  
  133.         private void CalculateRevs()  
  134.         {  
  135.             // calculate engine revs (for display / sound)  
  136.             // (this is done in retrospect - revs are not used in force/power calculations)  
  137.             CalculateGearFactor();  
  138.             var gearNumFactor = m_GearNum/(float) NoOfGears;  
  139.             var revsRangeMin = ULerp(0f, m_RevRangeBoundary, CurveFactor(gearNumFactor));  
  140.             var revsRangeMax = ULerp(m_RevRangeBoundary, 1f, gearNumFactor);  
  141.             Revs = ULerp(revsRangeMin, revsRangeMax, m_GearFactor);  
  142.         }  
  143.   
  144.         //运动函数,最重要  
  145.         public void Move(float steering, float accel, float footbrake, float handbrake)  
  146.         {  
  147.             //保持当前轮胎网格跟随wheelcolliders转动  
  148.             for (int i = 0; i < 4; i++)  
  149.             {  
  150.                 Quaternion quat;//四元数quat,用于旋转  
  151.                 Vector3 position;  
  152.                 m_WheelColliders[i].GetWorldPose(out position, out quat);//获取wheelcolliders的姿势,位置和转向角  
  153.                 //设置网格物体的位置和转向角  
  154.                 m_WheelMeshes[i].transform.position = position;  
  155.                 m_WheelMeshes[i].transform.rotation = quat;  
  156.             }  
  157.   
  158.             //clamp input values  
  159.             steering = Mathf.Clamp(steering, -1, 1);//限制steering的值在-1和1之间,以下同上  
  160.             AccelInput = accel = Mathf.Clamp(accel, 0, 1);  
  161.             BrakeInput = footbrake = -1*Mathf.Clamp(footbrake, -1, 0);  
  162.             handbrake = Mathf.Clamp(handbrake, 0, 1);  
  163.   
  164.             //Set the steer on the front wheels.  
  165.             //Assuming that wheels 0 and 1 are the front wheels.  
  166.             //设置前轮转向角,0,1为前轮,汽车行驶时也只是控制前轮转向  
  167.             m_SteerAngle = steering*m_MaximumSteerAngle;  
  168.             m_WheelColliders[0].steerAngle = m_SteerAngle;  
  169.             m_WheelColliders[1].steerAngle = m_SteerAngle;  
  170.             //调用角度辅助助手  
  171.             SteerHelper();  
  172.             //设置加速/刹车信息到WheelCollider  
  173.             ApplyDrive(accel, footbrake);  
  174.             //检查速度范围  
  175.             CapSpeed();  
  176.   
  177.             //Set the handbrake.设置手刹  
  178.             //Assuming that wheels 2 and 3 are the rear wheels.2,3代表后轮  
  179.             if (handbrake > 0f)  
  180.             {  
  181.                 //设置手刹值到后轮,达到减速目的  
  182.                 var hbTorque = handbrake*m_MaxHandbrakeTorque;  
  183.                 m_WheelColliders[2].brakeTorque = hbTorque;  
  184.                 m_WheelColliders[3].brakeTorque = hbTorque;  
  185.             }  
  186.   
  187.             //计算转速,用来供外部调用转速属性Revs来播放引擎声音等  
  188.             CalculateRevs();  
  189.             //改变档位  
  190.             GearChanging();  
  191.             //施加下压力  
  192.             AddDownForce();  
  193.             //检查轮胎  
  194.             CheckForWheelSpin();  
  195.             //牵引力控制系统  
  196.             TractionControl();  
  197.         }  
  198.   
  199.         //检查速度范围  
  200.         private void CapSpeed()  
  201.         {  
  202.             float speed = m_Rigidbody.velocity.magnitude;//将标量速度赋予speed  
  203.             //判断速度类型,  
  204.             switch (m_SpeedType)  
  205.             {  
  206.                 case SpeedType.MPH:  
  207.   
  208.                     speed *= 2.23693629f;  
  209.                     if (speed > m_Topspeed)  
  210.                         m_Rigidbody.velocity = (m_Topspeed/2.23693629f) * m_Rigidbody.velocity.normalized;//速度归一化  
  211.                     break;  
  212.   
  213.                 case SpeedType.KPH:  
  214.                     speed *= 3.6f;  
  215.                     if (speed > m_Topspeed)  
  216.                         m_Rigidbody.velocity = (m_Topspeed/3.6f) * m_Rigidbody.velocity.normalized;  
  217.                     break;  
  218.             }  
  219.         }  
  220.   
  221.         //设置加速/刹车信息到WheelCollider  
  222.         private void ApplyDrive(float accel, float footbrake)  
  223.         {  
  224.   
  225.             float thrustTorque;  
  226.             switch (m_CarDriveType)  
  227.             {  
  228.                 case CarDriveType.FourWheelDrive:  
  229.                     thrustTorque = accel * (m_CurrentTorque / 4f);  
  230.                     for (int i = 0; i < 4; i++)  
  231.                     {  
  232.                         m_WheelColliders[i].motorTorque = thrustTorque;  
  233.                     }  
  234.                     break;  
  235.   
  236.                 case CarDriveType.FrontWheelDrive:  
  237.                     thrustTorque = accel * (m_CurrentTorque / 2f);  
  238.                     m_WheelColliders[0].motorTorque = m_WheelColliders[1].motorTorque = thrustTorque;  
  239.                     break;  
  240.   
  241.                 case CarDriveType.RearWheelDrive:  
  242.                     thrustTorque = accel * (m_CurrentTorque / 2f);  
  243.                     m_WheelColliders[2].motorTorque = m_WheelColliders[3].motorTorque = thrustTorque;  
  244.                     break;  
  245.   
  246.             }  
  247.   
  248.             for (int i = 0; i < 4; i++)  
  249.             {  
  250.                 if (CurrentSpeed > 5 && Vector3.Angle(transform.forward, m_Rigidbody.velocity) < 50f)  
  251.                 {  
  252.                     m_WheelColliders[i].brakeTorque = m_BrakeTorque*footbrake;  
  253.                 }  
  254.                 else if (footbrake > 0)  
  255.                 {  
  256.                     m_WheelColliders[i].brakeTorque = 0f;  
  257.                     m_WheelColliders[i].motorTorque = -m_ReverseTorque*footbrake;  
  258.                 }  
  259.             }  
  260.         }  
  261.   
  262.         //此函数时move函数用于转向角  
  263.         private void SteerHelper()  
  264.         {  
  265.             for (int i = 0; i < 4; i++)  
  266.             {  
  267.                 WheelHit wheelhit;  
  268.                 m_WheelColliders[i].GetGroundHit(out wheelhit);  
  269.                 if (wheelhit.normal == Vector3.zero)  
  270.                     return// wheels arent on the ground so dont realign the rigidbody velocity 车轮离地,则不用调整汽车角度了。  
  271.             }  
  272.   
  273.             // this if is needed to avoid gimbal lock problems that will make the car suddenly shift direction  
  274.             //使用四元数避免万向锁的问题  
  275.             //假如上一次车体Y方向角度比这次小于十度,就根据相差的度数乘以系数m_SteerHelper,得出需要旋转的度数  
  276.             //根据这个度数算出四元数,然后将刚体速度直接旋转这个偏移度数  
  277.             if (Mathf.Abs(m_OldRotation - transform.eulerAngles.y) < 10f)  
  278.             {  
  279.                 var turnadjust = (transform.eulerAngles.y - m_OldRotation) * m_SteerHelper;  
  280.                 Quaternion velRotation = Quaternion.AngleAxis(turnadjust, Vector3.up);  
  281.                 m_Rigidbody.velocity = velRotation * m_Rigidbody.velocity;  
  282.             }  
  283.             m_OldRotation = transform.eulerAngles.y;  
  284.         }  
  285.   
  286.   
  287.         // this is used to add more grip in relation to speed  
  288.         //这个是用来增加下压力,这是用来添加更多的速度控制  
  289.         private void AddDownForce()  
  290.         {  
  291.             m_WheelColliders[0].attachedRigidbody.AddForce(-transform.up*m_Downforce*  
  292.                                                          m_WheelColliders[0].attachedRigidbody.velocity.magnitude);//Addforce 第一个车轮增加一个力,  
  293.         }  
  294.   
  295.   
  296.         // checks if the wheels are spinning and is so does three things 检查轮胎是否旋转  
  297.         // 1) emits particles 是否发射粒子  
  298.         // 2) plays tiure skidding sounds 播放滑行音  
  299.         // 3) leaves skidmarks on the ground 去掉刹车印  
  300.         // these effects are controlled through the WheelEffects class 这些特效都是通过类WheelEffects实现的  
  301.         private void CheckForWheelSpin()  
  302.         {  
  303.             // loop through all wheels 遍历所有车轮  
  304.             for (int i = 0; i < 4; i++)  
  305.             {  
  306.                 WheelHit wheelHit;  
  307.                 m_WheelColliders[i].GetGroundHit(out wheelHit);//获取碰撞信息  
  308.   
  309.                 // is the tire slipping above the given threshhold  
  310.                 //轮胎下滑超过给定的阈值吗  
  311.                 if (Mathf.Abs(wheelHit.forwardSlip) >= m_SlipLimit || Mathf.Abs(wheelHit.sidewaysSlip) >= m_SlipLimit)  
  312.                 {  
  313.                     //超出则发射烟雾粒子  
  314.                     m_WheelEffects[i].EmitTyreSmoke();  
  315.   
  316.                     // avoiding all four tires screeching at the same time  
  317.                     // if they do it can lead to some strange audio artefacts  
  318.                     //避免四个轮胎都同时播放滑行声音  
  319.                     //如果那样的话会导致某些奇怪的音效  
  320.                     //函数AnySkidSoundPlaying()是遍历四个轮子,检查是否播放音效,是的返回ture.  
  321.                     if (!AnySkidSoundPlaying())  
  322.                     {  
  323.                         m_WheelEffects[i].PlayAudio();  
  324.                     }  
  325.                     continue;  
  326.                 }  
  327.   
  328.                 // if it wasnt slipping stop all the audio  
  329.                 //假如没有超出阈值,还没有停止音效,则停止音效  
  330.                 if (m_WheelEffects[i].PlayingAudio)  
  331.                 {  
  332.                     m_WheelEffects[i].StopAudio();  
  333.                 }  
  334.                 // end the trail generation  
  335.                 //停止烟雾生成  
  336.                 m_WheelEffects[i].EndSkidTrail();  
  337.             }  
  338.         }  
  339.   
  340.   
  341.         //如果汽车轮胎过度滑转,牵引力系统可以控制减少轮胎动力  
  342.         // crude traction control that reduces the power to wheel if the car is wheel spinning too much  
  343.         private void TractionControl()//牵引力控制函数  
  344.         {  
  345.             WheelHit wheelHit;  
  346.             //判断驱动类型,四轮,还是前后轮,然后调用AdjustTorque函数  
  347.             switch (m_CarDriveType)  
  348.             {  
  349.                 case CarDriveType.FourWheelDrive:  
  350.                     // loop through all wheels  
  351.                     for (int i = 0; i < 4; i++)  
  352.                     {  
  353.                         m_WheelColliders[i].GetGroundHit(out wheelHit);  
  354.   
  355.                         AdjustTorque(wheelHit.forwardSlip);  
  356.                     }  
  357.                     break;  
  358.   
  359.                 case CarDriveType.RearWheelDrive:  
  360.                     m_WheelColliders[2].GetGroundHit(out wheelHit);  
  361.                     AdjustTorque(wheelHit.forwardSlip);  
  362.   
  363.                     m_WheelColliders[3].GetGroundHit(out wheelHit);  
  364.                     AdjustTorque(wheelHit.forwardSlip);  
  365.                     break;  
  366.   
  367.                 case CarDriveType.FrontWheelDrive:  
  368.                     m_WheelColliders[0].GetGroundHit(out wheelHit);  
  369.                     AdjustTorque(wheelHit.forwardSlip);  
  370.   
  371.                     m_WheelColliders[1].GetGroundHit(out wheelHit);  
  372.                     AdjustTorque(wheelHit.forwardSlip);  
  373.                     break;  
  374.             }  
  375.         }  
  376.   
  377.         //当向前滑动距离超过阈值后,就说明轮胎过度滑转,则减少牵引力,以降低转速。上面函数调用  
  378.         private void AdjustTorque(float forwardSlip)  
  379.         {  
  380.             if (forwardSlip >= m_SlipLimit && m_CurrentTorque >= 0)  
  381.             {  
  382.                 m_CurrentTorque -= 10 * m_TractionControl;  
  383.             }  
  384.             else  
  385.             {  
  386.                 m_CurrentTorque += 10 * m_TractionControl;  
  387.                 if (m_CurrentTorque > m_FullTorqueOverAllWheels)  
  388.                 {  
  389.                     m_CurrentTorque = m_FullTorqueOverAllWheels;  
  390.                 }  
  391.             }  
  392.         }  
  393.   
  394.         //函数AnySkidSoundPlaying()是遍历四个轮子,检查是否播放音效,是的返回ture.上面检查函数调用  
  395.         private bool AnySkidSoundPlaying()  
  396.         {  
  397.             for (int i = 0; i < 4; i++)  
  398.             {  
  399.                 if (m_WheelEffects[i].PlayingAudio)  
  400.                 {  
  401.                     return true;  
  402.                 }  
  403.             }  
  404.             return false;  
  405.         }  
  406.     }  
  407. }  
阅读更多
个人分类: Unity3d
上一篇提取手机游戏资源 特效 显存分析工具 无视任何加密
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭
关闭