【Unity3D赛车游戏】【四】在Unity中添加阿克曼转向,下压力,质心会让汽车更稳定


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

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

👨‍💻 本文由 秩沅 原创

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

⭐🅰️Unity3D赛车游戏⭐



文章目录


⭐前言⭐

--
😶‍🌫️版本: Unity2021
😶‍🌫️适合人群:Unity初学者
😶‍🌫️学习目标:3D赛车游戏的基础制作
😶‍🌫️技能掌握:



🎶(A)车辆优化------阿克曼转向添加


😶‍🌫️认识阿克曼转向

引用:阿克曼转向是一种现代汽车的转向方式,也是移动机器人的一种运动模式,在汽车转弯的时候,内外轮转过的角度不一样,内侧轮胎转弯半径小于外侧轮胎

原理图:

_____________
简单理解 :一个杆子把左轮和右轮连接起来一起转。

左轮的旋转的半径小于右轮

优点 :大大减小了车轮转向需要的空间,转向更加稳定

  • 阿克曼公式:

β为汽车前外轮转角,α为汽车前内轮转角,K为两主销中心距,L为轴距。

😶‍🌫️区别:

  • 未添加阿克曼转向之前的原理:

    通过控制轮子的最大转向范围来转向

  • 添加之后

    更稳定,机动性更强

😶‍🌫️关键代码

  • 后轮距尺寸设置为1.5f ,轴距设置为2.55f ,radius 默认为6,radius 越大旋转的角度看起来越小
csharp 复制代码
 if (horizontal > 0 ) {
//后轮距尺寸设置为1.5f ,轴距设置为2.55f ,radius 默认为6,radius 越大旋转的角度看起来越小
            wheels[0].steerAngle = Mathf.Rad2Deg * Mathf.Atan(2.55f / (radius + (1.5f / 2))) * horizontal;
            wheels[1].steerAngle = Mathf.Rad2Deg * Mathf.Atan(2.55f / (radius - (1.5f / 2))) * horizontal;
        } else if (horizontal < 0 ) {                                                          
            wheels[0].steerAngle = Mathf.Rad2Deg * Mathf.Atan(2.55f / (radius - (1.5f / 2))) * horizontal;
            wheels[1].steerAngle = Mathf.Rad2Deg * Mathf.Atan(2.55f / (radius + (1.5f / 2))) * horizontal;

        } else {
            wheels[0].steerAngle =0;
            wheels[1].steerAngle =0;
        }

😶‍🌫️完整代码

csharp 复制代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//-------------------------------------
//---------------------------------------------------------------------------------------------------------------
//___________项目:       ______________
//___________功能:  车轮的运动
//___________创建者:_______秩沅________
//_____________________________________
//-------------------------------------

//驱动模式的选择
public enum EDriveType
{
    frontDrive,   //前轮驱动
    backDrive,    //后轮驱动
    allDrive      //四驱
}


public class WheelMove : MonoBehaviour
{
    //-------------------------------------------
    //四个轮子的碰撞器
    public WheelCollider[] wheels ;

    //网格的获取
    public GameObject[] wheelMesh;

    //扭矩力度
    public float motorflaot = 200f;
  
    //初始化三维向量和四元数
    private Vector3 wheelPosition = Vector3.zero;
    private Quaternion wheelRotation = Quaternion.identity;
    //-------------------------------------------

    //驱动模式选择 _默认前驱
    public EDriveType DriveType = EDriveType.frontDrive;

    //轮半径
    public float radius = 0.25f;


    private void FixedUpdate()
    {
        WheelsAnimation(); //车轮动画

        VerticalContorl(); //驱动管理

        HorizontalContolr(); //转向管理

    }


    //垂直轴方向管理(驱动管理)
    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); //扭矩马力归半
                    }
                }
                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); //扭矩马力归半
                    }
                }
                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
                    }
                }
                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 WheelsAnimation()
    {
        for (int i = 0; i < wheels.Length ; i++)
        {
            //获取当前空间的车轮位置 和 角度
            wheels[i].GetWorldPose(out wheelPosition, out wheelRotation);

            //赋值给
            wheelMesh[i].transform.position = wheelPosition;
            print(wheelRotation);
            wheelMesh[i].transform.rotation = wheelRotation * Quaternion .AngleAxis (90,Vector3 .forward );
           
        }
        
    }
}

        }
        
    }
}

🎶(B)车辆优化------车身持续稳定的优化


WheelMove脚本 ------> CarMoveControl脚本 更改脚本名


😶‍🌫️速度属性实时转换


  • 每小时多少公里 和 每秒多少米的对应关系 ------1m/s = 3.6km/h

速度属性建议改成Int类型 ,float类型会上下浮动不准确

csharp 复制代码
 //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之间
  • 相机测速 m/s
csharp 复制代码
  //相机监测实时速度
          Control = target.GetComponent<CarMoveControl>();

          speed = (int )Control.Km_H / 4;
        
          speed = Mathf.Clamp(0, 55,speed );   //对应最大200公里每小时
  • 添加四个轮子的实时速度,对应虚度属性,可以明显的观察四驱和二驱的汽车动力
csharp 复制代码
    //车辆物理属性相关
    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;
    }

😶‍🌫️为车子添加下压力


知识百科: 什么是下压力

下压力是车在行进中空气在车体上下流速不一产生的,使空气的总压力指向地面从而增加车的抓地力.

速度越大,下压力越大,抓地更强,越不易翻车

  • 关键代码
csharp 复制代码
  //-------------下压力添加-----------------

        //速度越大,下压力越大,抓地更强
        rigidbody.AddForce(-transform.up * downForceValue * rigidbody.velocity .magnitude );

😶‍🌫️质心的添加centerMess


知识百科:什么是质心?------质量中心

汽车制造商在设计汽车时会考虑质心的位置和重心高度,以尽可能减小质心侧偏角。 一些高性能汽车甚至会采用主动悬挂系统来控制车身侧倾,从而减小质心侧偏角,提高车辆的稳定性和操控性。

质量中心越贴下,越不容易翻

csharp 复制代码
        //-------------质量中心同步----------------

        //质量中心越贴下,越不容易翻
        rigidbody.centerOfMass = CenterMass;
  • 手刹的添加
csharp 复制代码
        //手刹管理
    public void HandbrakControl()
    {
        if(InputManager.InputManagerment .handbanl )
        {     
            //后轮刹车
            wheels[2].brakeTorque  = brakVualue;
            wheels[3].brakeTorque  = brakVualue;
        }
        else
        {
            wheels[2].brakeTorque = 0;
            wheels[3].brakeTorque = 0;
        }
    }

😶‍🌫️轮胎的平滑度的显示


wheelhit.forwardSlip;用来观看刹车轮胎在滚动方向上打滑。加速滑移为负,制动滑为正

_______

csharp 复制代码
    for (int i = 0; i < slip.Length; i++)
    {
            WheelHit wheelhit;

            wheels[i].GetGroundHit(out wheelhit);

            slip[i] = wheelhit.forwardSlip; //轮胎在滚动方向上打滑。加速滑移为负,制动滑为正
    }               

⭐🅰️⭐



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

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

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

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

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

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

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


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



相关推荐
cyr___17 分钟前
Unity教程(十六)敌人攻击状态的实现
学习·游戏·unity·游戏引擎
迪捷软件36 分钟前
知识|智能网联汽车多域电子电气架构会如何发展?
架构·汽车
nbsaas-boot40 分钟前
架构卡牌游戏:通过互动与挑战学习系统设计的创新玩法
学习·游戏·架构
FairGuard手游加固44 分钟前
游戏如何应对云手机刷量问题
游戏
哆木1 小时前
部署在线GBA游戏,并通过docker安装启动
游戏·html·gba
friklogff1 小时前
【C#生态园】构建你的C#操作系统:框架选择与实践
服务器·开发语言·c#
code bean4 小时前
【C#基础】函数传参大总结
服务器·开发语言·c#
shanshan20995 小时前
上位机系统架构 | 如何设计一个高效的多相机管理系统
c#·wpf·相机
ling1s6 小时前
C#基础(13)结构体
前端·c#
.Net Core 爱好者7 小时前
Redis实践之缓存:设置缓存过期策略
java·redis·缓存·c#·.net