上海古都建筑设计集团,上海办公室装修设计公司,上海装修公司高质量的内容分享社区,上海装修公司我们不是内容生产者,我们只是上海办公室装修设计公司内容的搬运工平台

【Unity3D赛车游戏】【六】如何在Unity中为汽车添加发动机和手动挡变速?

guduadmin211月前

【Unity3D赛车游戏】【六】如何在Unity中为汽车添加发动机和手动挡变速?,在这里插入图片描述,第1张


👨‍💻个人主页:@元宇宙-秩沅

👨‍💻 hallo 欢迎 点赞👍 收藏⭐ 留言📝 加关注✅!

👨‍💻 本文由 秩沅 原创

👨‍💻 收录于专栏:Unity游戏demo

🅰️Unity3D赛车游戏



文章目录

    • 🅰️Unity3D赛车游戏
    • 前言
      • 常见问题
      • 🎶(==A==)车辆模型——绘制发动机马力与转速曲线
          • 😶‍🌫️添加并绘制AnimationCurve 动画曲线
          • 😶‍🌫️AnimationCurve .EvaluateAPI
          • 🎶(==B==)车辆模型——发动机和手动挡位的初步实现
              • 😶‍🌫️添加发动机相关的属性
              • 😶‍🌫️更新输入控制脚本增添换挡输入
              • 😶‍🌫️换挡管理,挡位比率
              • 🎶(==C==)车辆模型——脚本记录
                  • 😶‍🌫️CarMoveControl
                  • 😶‍🌫️CameraContorl
                  • 😶‍🌫️UIContorl
                  • 😶‍🌫️ InputManager

                    前言

                    😶‍🌫️版本: Unity2021

                    😶‍🌫️适合人群:Unity初学者

                    😶‍🌫️学习目标:3D赛车游戏的基础制作

                    😶‍🌫️技能掌握:


                    常见问题


                    🎶(A车辆模型——绘制发动机马力与转速曲线


                    😶‍🌫️添加并绘制AnimationCurve 动画曲线

                    shift控制Y轴伸缩,ctrl控制x轴伸缩

                    【Unity3D赛车游戏】【六】如何在Unity中为汽车添加发动机和手动挡变速?,在这里插入图片描述,第2张

                    • 跑车发动机一般是7百左右,我们就按照跑车的最大功率来做

                      【Unity3D赛车游戏】【六】如何在Unity中为汽车添加发动机和手动挡变速?,在这里插入图片描述,第3张


                      😶‍🌫️AnimationCurve .EvaluateAPI

                      通过X轴获取Y轴值

                      【Unity3D赛车游戏】【六】如何在Unity中为汽车添加发动机和手动挡变速?,在这里插入图片描述,第4张


                      🎶(B车辆模型——发动机和手动挡位的初步实现


                      😶‍🌫️添加发动机相关的属性

                      【Unity3D赛车游戏】【六】如何在Unity中为汽车添加发动机和手动挡变速?,在这里插入图片描述,第5张

                      【Unity3D赛车游戏】【六】如何在Unity中为汽车添加发动机和手动挡变速?,在这里插入图片描述,第6张

                      发动机功率=扭矩转速n

                      知识百科:说到汽车发动机,要了解几个参数。排量,功率,扭矩,转速。那么这里和参数之间的关系如何,

                      排量,就是发动机气缸排出气体的多少。因此说到排量,不管四缸,三缸,二缸,一缸,只要大小一样,排量就相同。

                      功率,单位时间内做功的多少。那么排量越大,单位时间做功就会越多,因此,排量越大,功率也会越大。

                      扭矩,它的单位是N·M,所以它是力运动单位距离的结果。它反应的是加速度。扭矩越大,加速能力就越强。

                      转速,它是单位时间内齿轮转动的圈数。齿轮转的越快,传输给轮胎的转速就越高,车子就跑的越快。

                      • 关键代码
                            //汽车引擎发动机相关
                            public void CarEnginePower()
                            {
                                WheelRPM();//将轮轴的转速获取
                                // 扭矩力(发动机功率) =  功率=扭矩*转速*n
                                
                                motorflaot = -enginePowerCurve.Evaluate(engineRPM)* gears[gerrsNurrentNum] * InputManager.InputManagerment.vertical;
                                float velocity = 0.0f;
                                //发动机的转速 与 车轮转速 和 挡位比率 成比例
                                engineRPM = Mathf.SmoothDamp(engineRPM, 1000 + Mathf.Abs(wheelsRPM) * 3.6f * (gears[gerrsNurrentNum]), ref velocity, smoothTime);
                                print(engineRPM);
                                VerticalContorl(); //驱动管理
                            }
                        

                        【Unity3D赛车游戏】【六】如何在Unity中为汽车添加发动机和手动挡变速?,在这里插入图片描述,第7张


                        😶‍🌫️更新输入控制脚本增添换挡输入

                        using System.Collections;
                        using System.Collections.Generic;
                        using UnityEngine;
                        //-------------------------------------
                        //—————————————————————————————————————
                        //___________项目:       
                        //___________功能: 输入控制管理器
                        //___________创建者:秩沅_______________
                        //_____________________________________
                        //-------------------------------------
                        public class InputManager : MonoBehaviour
                        {
                            //单例模式管理
                            static private InputManager inputManagerment;
                            static public InputManager InputManagerment => inputManagerment;
                            public float horizontal;  //水平方向动力值
                            public float vertical;    //垂直方向动力值
                            public bool  handbanl;    //手刹动力值
                            public bool shiftSpeed;   //加速shift键
                            //public float clutch;    //离合器
                            public bool addGears;     //升档
                            public bool lowGears;     //降档
                            void Awake()
                            {
                                inputManagerment = this;
                            }
                            void FixedUpdate()
                            {
                                //与Unity中输入管理器的值相互对应
                                horizontal = Input.GetAxis("Horizontal");
                                  vertical = Input.GetAxis("Vertical");
                                  handbanl = Input.GetAxis("Jump")!= 0 ? true :false ; //按下空格键时就是1,否则为0
                                shiftSpeed = Input.GetKey(KeyCode.LeftShift) ? true : false;
                                //clutch   = Input.GetKey(KeyCode.LeftShift) ? 0 : Mathf.Lerp(clutch ,1,Time .deltaTime);
                                addGears   = Input.GetKeyDown(KeyCode.E ) ? true : false;
                                lowGears   = Input.GetKeyDown(KeyCode.Q ) ? true : false;
                            }
                        }
                        

                        😶‍🌫️换挡管理,挡位比率

                        【Unity3D赛车游戏】【六】如何在Unity中为汽车添加发动机和手动挡变速?,在这里插入图片描述,第8张

                            //换挡管理
                            public void shifterGearsChange()
                            {
                                if(InputManager.InputManagerment .addGears ) //如果按下E键,加挡
                                {
                                    if(gerrsNurrentNum < gears.Length - 1  )
                                    gerrsNurrentNum++;
                                }
                                if(InputManager.InputManagerment.lowGears ) //如果按下Q键,减档
                                {
                                    if (gerrsNurrentNum > 0)
                                        gerrsNurrentNum--;
                                }
                            }
                        

                        🎶(C车辆模型——脚本记录


                        【Unity3D赛车游戏】【六】如何在Unity中为汽车添加发动机和手动挡变速?,在这里插入图片描述,第9张

                        【Unity3D赛车游戏】【六】如何在Unity中为汽车添加发动机和手动挡变速?,在这里插入图片描述,第10张

                        😶‍🌫️CarMoveControl
                        using System.Collections;
                        using System.Collections.Generic;
                        using UnityEngine;
                        //-------------------------------------
                        //—————————————————————————————————————
                        //___________项目:       ______________
                        //___________功能:  车轮的运动
                        //___________创建者:_______秩沅________
                        //_____________________________________
                        //-------------------------------------
                        //驱动模式的选择
                        public enum EDriveType
                        {
                            frontDrive,   //前轮驱动
                            backDrive,    //后轮驱动
                            allDrive      //四驱
                        }
                        public class CarMoveControl : MonoBehaviour
                        {
                            //-------------------------------------------
                            [Header("----------轮碰撞器特征-------------")]
                            //四个轮子的碰撞器
                            public WheelCollider[] wheels;
                            [SerializeField]
                            //网格的获取
                            private GameObject[] wheelMesh;
                            //四个轮胎扭矩力的大小
                            public float f_right;
                            public float f_left;
                            public float b_right;
                            public float b_left;
                            //车轮打滑参数识别
                            public float[] slip;
                            //初始化三维向量和四元数
                            private Vector3 wheelPosition = Vector3.zero;
                            private Quaternion wheelRotation = Quaternion.identity;
                            //-------------------------------------------
                            //驱动模式选择 _默认前驱
                            public EDriveType DriveType = EDriveType.frontDrive;
                            [Header("----------车辆属性特征-------------")]
                            //车刚体
                            public Rigidbody rigidbody;
                            //轮半径
                            public float radius = 0.25f;
                            //扭矩力度
                            public float motorflaot = 8000f;
                            //刹车力
                            public float brakVualue = 800000f;
                            //速度:每小时多少公里
                            public int Km_H;
                            //加速的速度增量
                            public float shiftSpeed = 4000;
                            //下压力
                            public float downForceValue = 1000f;
                            //质心
                            public Vector3 CenterMass;
                            [Header("----------发动机属性特征-------------")]
                            //发动机马力与转速曲线
                            public AnimationCurve enginePowerCurve;
                            //车轮的RPM平均转速
                            public float wheelsRPM;
                            //发动机转速
                            public float engineRPM;
                            //汽车齿轮比(挡位)
                            public float[] gears;
                            //当前的挡位
                            public int gerrsNurrentNum = 0;
                            //差速比
                            public float diffrirentialRation;
                            //离合器
                            private float clutch;
                            //平滑时间参数
                            private float smoothTime = 0.09f;
                            //一些属性的初始化
                            private void Start()
                            {
                                rigidbody = GetComponent();
                                slip = new float[4];
                            }
                            private void FixedUpdate()
                            {
                                VerticalAttribute();//车辆物理属性管理
                                WheelsAnimation(); //车轮动画
                                CarEnginePower(); //汽车发动机
                               
                                HorizontalContolr(); //转向管理
                                HandbrakControl(); //手刹管理
                                ShiftSpeed();//加速相关
                            }
                            //车辆物理属性相关
                            public void VerticalAttribute()
                            {
                                //---------------速度实时---------------
                                //1m/s = 3.6km/h
                                Km_H = (int)(rigidbody.velocity.magnitude * 3.6);
                                Km_H = Mathf.Clamp(Km_H, 0, 200);   //油门速度为 0 到 200 Km/H之间
                                //--------------扭矩力实时---------------
                                //显示每个轮胎的扭矩
                                f_right = wheels[0].motorTorque;
                                f_left = wheels[1].motorTorque;
                                b_right = wheels[2].motorTorque;
                                b_left = wheels[3].motorTorque;
                                //-------------下压力添加-----------------
                                //速度越大,下压力越大,抓地更强
                                rigidbody.AddForce(-transform.up * downForceValue * rigidbody.velocity.magnitude);
                                //-------------质量中心同步----------------
                                //质量中心越贴下,越不容易翻
                                rigidbody.centerOfMass = CenterMass;
                            }
                            //垂直轴方向运动管理(驱动管理)
                            public void VerticalContorl()
                            {
                                switch (DriveType)
                                {
                                    case EDriveType.frontDrive:
                                        //选择前驱
                                        if (InputManager.InputManagerment.vertical != 0) //当按下WS键时生效
                                        {
                                            for (int i = 0; i < wheels.Length - 2; i++)
                                            {
                                                //扭矩力度
                                                wheels[i].motorTorque = InputManager.InputManagerment.vertical * (motorflaot / 2); //扭矩马力归半
                                            }
                                        }
                                        else
                                        {
                                            for (int i = 0; i < wheels.Length - 2; i++)
                                            {
                                                //扭矩力度
                                                wheels[i].motorTorque = 0;
                                            }
                                        }
                                        break;
                                    case EDriveType.backDrive:
                                        //选择后驱
                                        if (InputManager.InputManagerment.vertical != 0) //当按下WS键时生效
                                        {
                                            for (int i = 2; i < wheels.Length; i++)
                                            {
                                                //扭矩力度
                                                wheels[i].motorTorque = InputManager.InputManagerment.vertical * (motorflaot / 2); //扭矩马力归半
                                            }
                                        }
                                        else
                                        {
                                            for (int i = 2; i < wheels.Length; i++)
                                            {
                                                //扭矩力度
                                                wheels[i].motorTorque = 0;
                                            }
                                        }
                                        break;
                                    case EDriveType.allDrive:
                                        //选择四驱
                                        if (InputManager.InputManagerment.vertical != 0) //当按下WS键时生效
                                        {
                                            for (int i = 0; i < wheels.Length; i++)
                                            {
                                                //扭矩力度
                                                wheels[i].motorTorque = InputManager.InputManagerment.vertical * (motorflaot / 4); //扭矩马力/4
                                            }
                                        }
                                        else
                                        {
                                            for (int i = 0; i < wheels.Length; i++)
                                            {
                                                //扭矩力度
                                                wheels[i].motorTorque = 0;
                                            }
                                        }
                                        break;
                                    default:
                                        break;
                                }
                            }
                            //水平轴方向运动管理(转向管理)
                            public void HorizontalContolr()
                            {
                                if (InputManager.InputManagerment.horizontal > 0)
                                {
                                    //后轮距尺寸设置为1.5f ,轴距设置为2.55f ,radius 默认为6,radius 越大旋转的角度看起来越小
                                    wheels[0].steerAngle = Mathf.Rad2Deg * Mathf.Atan(2.55f / (radius + (1.5f / 2))) * InputManager.InputManagerment.horizontal;
                                    wheels[1].steerAngle = Mathf.Rad2Deg * Mathf.Atan(2.55f / (radius - (1.5f / 2))) * InputManager.InputManagerment.horizontal;
                                }
                                else if (InputManager.InputManagerment.horizontal < 0)
                                {
                                    wheels[0].steerAngle = Mathf.Rad2Deg * Mathf.Atan(2.55f / (radius - (1.5f / 2))) * InputManager.InputManagerment.horizontal;
                                    wheels[1].steerAngle = Mathf.Rad2Deg * Mathf.Atan(2.55f / (radius + (1.5f / 2))) * InputManager.InputManagerment.horizontal;
                                }
                                else
                                {
                                    wheels[0].steerAngle = 0;
                                    wheels[1].steerAngle = 0;
                                }
                            }
                            //手刹管理
                            public void HandbrakControl()
                            {
                                if (InputManager.InputManagerment.handbanl)
                                {
                                    //后轮刹车
                                    wheels[2].brakeTorque = brakVualue;
                                    wheels[3].brakeTorque = brakVualue;
                                }
                                else
                                {
                                    wheels[2].brakeTorque = 0;
                                    wheels[3].brakeTorque = 0;
                                }
                                //------------刹车效果平滑度显示------------
                                for (int i = 0; i < slip.Length; i++)
                                {
                                    WheelHit wheelhit;
                                    wheels[i].GetGroundHit(out wheelhit);
                                    slip[i] = wheelhit.forwardSlip; //轮胎在滚动方向上打滑。加速滑移为负,制动滑为正
                                }
                            }
                            //车轮动画相关
                            public void WheelsAnimation()
                            {
                                for (int i = 0; i < wheels.Length; i++)
                                {
                                    //获取当前空间的车轮位置 和 角度
                                    wheels[i].GetWorldPose(out wheelPosition, out wheelRotation);
                                    //赋值给
                                    wheelMesh[i].transform.position = wheelPosition;
                                    wheelMesh[i].transform.rotation = wheelRotation * Quaternion.AngleAxis(90, Vector3.forward);
                                }
                            }
                            //加速以及动画相关
                            public void ShiftSpeed()
                            {
                                //按下shift加速键时
                                if (InputManager.InputManagerment.shiftSpeed)
                                {
                                    //向前增加一个力
                                    rigidbody.AddForce(-transform.forward * shiftSpeed);
                                }
                                else
                                {
                                    rigidbody.AddForce(transform.forward * 0);
                                }
                            }
                            //汽车引擎发动机相关
                            public void CarEnginePower()
                            {
                                WheelRPM();//将轮轴的转速获取
                                // 扭矩力(发动机功率) =  功率=扭矩*转速*n
                                motorflaot = -enginePowerCurve.Evaluate(engineRPM) * gears[gerrsNurrentNum];
                                float velocity = 0.0f;
                                //发动机的转速 与 车轮转速 和 挡位比率 成比例
                                engineRPM = Mathf.SmoothDamp(engineRPM, 1000 + Mathf.Abs (wheelsRPM) * 3.6f * (gears[gerrsNurrentNum]), ref velocity, smoothTime);
                                print(engineRPM);
                                VerticalContorl();    //驱动管理
                                shifterGearsChange(); //换挡管理
                            }
                            //获得车轮的转速
                            public void WheelRPM()
                            {
                                float sum = 0;
                                for (int i = 0; i < 4; i++)
                                {
                                    sum += wheels[i].rpm;
                                }
                                //四个车轮轮轴的平均转速
                                wheelsRPM = sum / 4;
                            }
                            //换挡管理
                            public void shifterGearsChange()
                            {
                                if(InputManager.InputManagerment .addGears ) //如果按下E键,加挡
                                {
                                    if(gerrsNurrentNum < gears.Length - 1  )
                                    gerrsNurrentNum++;
                                }
                                if(InputManager.InputManagerment.lowGears ) //如果按下Q键,减档
                                {
                                    if (gerrsNurrentNum > 0)
                                        gerrsNurrentNum--;
                                }
                            }
                        }
                        
                        😶‍🌫️CameraContorl
                        using System.Collections;
                        using System.Collections.Generic;
                        using UnityEngine;
                        //-------------------------------------
                        //—————————————————————————————————————
                        //___________项目:       ______________
                        //___________功能: 相机的管理
                        //___________创建者:秩沅_______________
                        //_____________________________________
                        //-------------------------------------
                        public class CameraContorl : MonoBehaviour
                        {
                            //目标物体
                            public Transform target;
                            private CarMoveControl Control;
                            public float  speed;
                            [Header("----------相机基础属性-------------")]
                            //鼠标滑轮的速度
                            public float ScrollSpeed = 45f;
                         
                            public  float Ydictance = 0f;
                            private float  Ymin = 0f;
                            private float  Ymax  = 4f;
                            public   float Zdictance = 4f;
                            private float Zmin = 4f;
                            private float Zmax = 15f;
                            //相机看向的角度 和最終位置
                            public float angle = -25 ;
                            private Vector3 lastPosition;
                            private Vector3 lookPosition;
                            [Header("----------加速时相机属性-------------")]
                            //加速时的跟随力度
                            [Range(1, 5)]
                            public float shiftOff;
                            //目标视野 (让其显示可见)
                            [SerializeField ]
                            private float addFov;
                            //当前视野
                            private float startView;
                            public float off = 20;
                            //为一些属性初始化
                            private void Start()
                            {
                                startView = Camera.main.fieldOfView; //将相机的开始属性赋入
                                addFov = 30;
                            }
                            void LateUpdate()
                            {
                                FllowEffect(); //相机属性显示
                                CameraAtrribute(); //相机跟随功能
                                FOXChange();  //加速时相机视野的变化
                            }
                            //相机属性显示
                            public void CameraAtrribute()
                            {
                                //实时速度
                                Control = target.GetComponent();
                                speed = Mathf .Lerp (speed , Control.Km_H / 4 ,Time.deltaTime ) ;
                                speed = Mathf.Clamp(speed, 0, 55);   //对应最大200公里每小时
                            }
                            //相机跟随功能
                            public void FllowEffect()  
                            {
                                //Z轴和Y轴的距离和鼠标滑轮联系
                                Ydictance += Input.GetAxis("Mouse ScrollWheel") * ScrollSpeed * Time.deltaTime;//平滑效果
                                Zdictance += Input.GetAxis("Mouse ScrollWheel") * ScrollSpeed * Time.deltaTime*2;
                                //設置Y軸和x轴的滚轮滑动范围 
                                Ydictance = Mathf.Clamp(Ydictance, Ymin, Ymax);
                                Zdictance = Mathf.Clamp(Zdictance, Zmin, Zmax);
                                //确定好角度,四元数 * 三维向量 = 三维向量 和最终位置
                                lookPosition = Quaternion.AngleAxis(angle, target.right) * -target.forward;
                                lastPosition = target.position + Vector3.up * Ydictance - lookPosition * Zdictance;
                                差值更新位置,速度越快镜头跟随越快,速度越慢镜头跟随越慢
                                transform.position = lastPosition;    
                                //更新角度
                                transform.rotation = Quaternion.LookRotation(lookPosition);
                            }
                            //加速时相机视野的变化
                            public void FOXChange()
                            {
                                if(Input.GetKey(KeyCode.LeftShift) ) //按下坐标shift键生效
                                {
                                    Camera.main.fieldOfView = Mathf.Lerp(Camera.main.fieldOfView , startView + addFov ,Time .deltaTime * shiftOff );
                                }
                                else
                                {
                                    Camera.main.fieldOfView = Mathf.Lerp(Camera.main.fieldOfView, startView, Time.deltaTime * shiftOff);
                                }
                            }
                        }
                        
                        😶‍🌫️UIContorl
                        using System.Collections;
                        using System.Collections.Generic;
                        using UnityEngine;
                        //-------------------------------------
                        //—————————————————————————————————————
                        //___________项目:       ______________
                        //___________功能:  UI相关的脚本管理
                        //___________创建者:_______秩沅________
                        //_____________________________________
                        //-------------------------------------
                        public class UIContorl : MonoBehaviour
                        {
                            //------------------仪表盘----------------
                            //速度指针开始角度和最终角度
                            private float startAngel = 215, ednAngel = -35;
                            //速度指针偏差角度
                            private float offAngel;
                            //获取速度的对象
                            public CarMoveControl control;
                            //速度指针组件
                            public Transform node;
                            //----------------------------------------
                            void Update()
                            {
                                //偏差角度 = 每度(速度)旋转的角度 * 速度
                                offAngel = (startAngel - ednAngel) / 180 * control.Km_H;
                                //offAngel = (startAngel - ednAngel)  * control.engineRPM /10000;
                                //仪表盘的管理,与速度同步
                                node.eulerAngles = new Vector3 (0, 0, startAngel -offAngel);
                            }
                        }
                        
                        😶‍🌫️ InputManager
                        using System.Collections;
                        using System.Collections.Generic;
                        using UnityEngine;
                        //-------------------------------------
                        //—————————————————————————————————————
                        //___________项目:       ______________
                        //___________功能: 输入控制管理器
                        //___________创建者:秩沅_______________
                        //_____________________________________
                        //-------------------------------------
                        public class InputManager : MonoBehaviour
                        {
                            //单例模式管理
                            static private InputManager inputManagerment;
                            static public InputManager InputManagerment => inputManagerment;
                            public float horizontal;  //水平方向动力值
                            public float vertical;    //垂直方向动力值
                            public bool  handbanl;    //手刹动力值
                            public bool shiftSpeed;   //加速shift键
                            //public float clutch;    //离合器
                            public bool addGears;     //升档
                            public bool lowGears;     //降档
                            void Awake()
                            {
                                inputManagerment = this;
                            }
                            void FixedUpdate()
                            {
                                //与Unity中输入管理器的值相互对应
                                horizontal = Input.GetAxis("Horizontal");
                                  vertical = Input.GetAxis("Vertical");
                                  handbanl = Input.GetAxis("Jump")!= 0 ? true :false ; //按下空格键时就是1,否则为0
                                shiftSpeed = Input.GetKey(KeyCode.LeftShift) ? true : false;
                                //clutch   = Input.GetKey(KeyCode.LeftShift) ? 0 : Mathf.Lerp(clutch ,1,Time .deltaTime);
                                addGears   = Input.GetKeyDown(KeyCode.E ) ? true : false;
                                lowGears   = Input.GetKeyDown(KeyCode.Q ) ? true : false;
                            }
                        }
                        

                        ⭐【Unityc#专题篇】之c#进阶篇】

                        ⭐【Unityc#专题篇】之c#核心篇】

                        ⭐【Unityc#专题篇】之c#基础篇】

                        ⭐【Unity-c#专题篇】之c#入门篇】

                        ⭐【Unityc#专题篇】—进阶章题单实践练习

                        ⭐【Unityc#专题篇】—基础章题单实践练习

                        ⭐【Unityc#专题篇】—核心章题单实践练习


                        你们的点赞👍 收藏⭐ 留言📝 关注✅是我持续创作,输出优质内容的最大动力!、


                        【Unity3D赛车游戏】【六】如何在Unity中为汽车添加发动机和手动挡变速?,在这里插入图片描述,第11张


网友评论

搜索
最新文章
热门文章
热门标签
 
 梦见哭的很伤心什么预兆  梦到被蛇咬出血  梦见坟墓是什么兆头