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

本文主要是介绍【Unity3D赛车游戏】【四】在Unity中添加阿克曼转向,下压力,质心会让汽车更稳定,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

在这里插入图片描述


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

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

👨‍💻 本文由 秩沅 原创

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

🅰️Unity3D赛车游戏



文章目录

    • 🅰️Unity3D赛车游戏
    • 前言
    • 🎶(==A==)车辆优化——阿克曼转向添加
        • 😶‍🌫️认识阿克曼转向
        • 😶‍🌫️区别:
        • 😶‍🌫️关键代码
        • 😶‍🌫️完整代码
    • 🎶(==B==)车辆优化——车身持续稳定的优化
        • 😶‍🌫️速度属性实时转换
        • 😶‍🌫️为车子添加下压力
        • 😶‍🌫️质心的添加centerMess
        • 😶‍🌫️轮胎的平滑度的显示
    • 🎶(==C==)脚本记录
    • CarMoveContorl
    • CameraFllow
    • InputMana
    • 🅰️


前言


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



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


😶‍🌫️认识阿克曼转向

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

原理图:
_____________在这里插入图片描述
简单理解一个杆子把左轮和右轮连接起来一起转。

在这里插入图片描述
左轮的旋转的半径小于右轮

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

  • 阿克曼公式:

在这里插入图片描述
β为汽车前外轮转角,α为汽车前内轮转角,K为两主销中心距,L为轴距。

在这里插入图片描述

😶‍🌫️区别:
  • 未添加阿克曼转向之前的原理:

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

在这里插入图片描述

  • 添加之后

    更稳定,机动性更强

在这里插入图片描述

😶‍🌫️关键代码
  • 后轮距尺寸设置为1.5f ,轴距设置为2.55f ,radius 默认为6,radius 越大旋转的角度看起来越小
 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;}
😶‍🌫️完整代码

在这里插入图片描述

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类型会上下浮动不准确

 //1m/s = 3.6km/hKm_H =(int)(rigidbody.velocity.magnitude * 3.6) ;Km_H = Mathf.Clamp( Km_H,0, 200 );   //油门速度为 0 到 200 Km/H之间
  • 相机测速 m/s
    在这里插入图片描述
  //相机监测实时速度Control = target.GetComponent<CarMoveControl>();speed = (int )Control.Km_H / 4;speed = Mathf.Clamp(0, 55,speed );   //对应最大200公里每小时
  • 添加四个轮子的实时速度,对应虚度属性,可以明显的观察四驱和二驱的汽车动力

在这里插入图片描述

    //车辆物理属性相关public void VerticalAttribute(){//1m/s = 3.6km/hKm_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 );

😶‍🌫️质心的添加centerMess

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

质量中心越贴下,越不容易翻
在这里插入图片描述

        //-------------质量中心同步----------------//质量中心越贴下,越不容易翻rigidbody.centerOfMass = CenterMass;
  • 手刹的添加
//手刹管理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;用来观看刹车轮胎在滚动方向上打滑。加速滑移为负,制动滑为正
_______在这里插入图片描述

for (int i = 0; i < slip.Length; i++){WheelHit wheelhit;wheels[i].GetGroundHit(out wheelhit);slip[i] = wheelhit.forwardSlip; //轮胎在滚动方向上打滑。加速滑移为负,制动滑为正}               

在这里插入图片描述
在这里插入图片描述


🎶(C脚本记录


在这里插入图片描述

CarMoveContorl

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//-------------------------------------
//—————————————————————————————————————
//___________项目:       ______________
//___________功能:  车轮的运动
//___________创建者:_______秩沅________
//_____________________________________
//-------------------------------------//驱动模式的选择
public enum EDriveType
{frontDrive,   //前轮驱动backDrive,    //后轮驱动allDrive      //四驱
}public class CarMoveControl : MonoBehaviour
{//-------------------------------------------//四个轮子的碰撞器public WheelCollider[] wheels ;//网格的获取public GameObject[] wheelMesh;//初始化三维向量和四元数private Vector3 wheelPosition = Vector3.zero;private Quaternion wheelRotation = Quaternion.identity;//-------------------------------------------//驱动模式选择 _默认前驱public EDriveType DriveType = EDriveType.frontDrive;//----------车辆属性特征-----------------------//车刚体public Rigidbody rigidbody;//轮半径public float radius = 0.25f;//扭矩力度public float motorflaot = 8000f;//刹车力public float brakVualue = 800000f;//速度:每小时多少公里public int Km_H;//下压力public float downForceValue = 1000f; //四个轮胎扭矩力的大小public float f_right;public float f_left;public float b_right;public float b_left;//车轮打滑参数识别public float[] slip ;//质心public Vector3 CenterMass;//一些属性的初始化private void Start(){rigidbody = GetComponent<Rigidbody>();slip = new float[4];}private void FixedUpdate(){VerticalAttribute();//车辆物理属性管理WheelsAnimation(); //车轮动画VerticalContorl(); //驱动管理HorizontalContolr(); //转向管理HandbrakControl(); //手刹管理}//车辆物理属性相关public void VerticalAttribute(){//---------------速度实时---------------//1m/s = 3.6km/hKm_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 );}}
}

CameraFllow

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//-------------------------------------
//—————————————————————————————————————
//___________项目:       ______________
//___________功能: 相机的跟随
//___________创建者:秩沅_______________
//_____________________________________
//-------------------------------------
public class CameraFllow : MonoBehaviour
{//目标物体public Transform target;private CarMoveControl Control;public int  speed;//鼠标滑轮的速度public float ScrollSpeed = 45f;//Y轴差距参数public float Ydictance = 0f; public float  Ymin = 0f;public float  Ymax  = 4f;//Z轴差距参数public float Zdictance = 4f;public float Zmin = 4f;public float Zmax = 8f;//相机看向的角度 和最終位置public float angle = -25 ;public Vector3 lookPosition;void LateUpdate(){//Z轴和Y轴的距离和鼠标滑轮联系Ydictance += Input.GetAxis("Mouse ScrollWheel") * ScrollSpeed * Time.deltaTime;//平滑效果Zdictance += Input.GetAxis("Mouse ScrollWheel") * ScrollSpeed * Time.deltaTime;//設置Y軸和x轴的滚轮滑动范围 Ydictance = Mathf.Clamp(Ydictance , Ymin ,Ymax )  ; Zdictance = Mathf.Clamp(Zdictance , Zmin, Zmax )  ;//确定好角度,四元数 * 三维向量 = 三维向量lookPosition = Quaternion.AngleAxis(angle, target .right) * -target.forward ;//更新位置transform.position = target.position + Vector3.up * Ydictance - lookPosition  * Zdictance  ;//更新角度transform.rotation = Quaternion.LookRotation(lookPosition);//实时速度Control = target.GetComponent<CarMoveControl>();speed = (int )Control.Km_H / 4;speed = Mathf.Clamp(speed,0, 55 );   //对应最大200公里每小时}
}

InputMana

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;    //手刹动力值void Awake(){inputManagerment = this;}void Update(){//与Unity中输入管理器的值相互对应horizontal = Input.GetAxis("Horizontal");vertical = Input.GetAxis("Vertical");handbanl = Input.GetAxis("Jump")!= 0 ? true :false ; //按下空格键时就是1,否则为0}
}

🅰️

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

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

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

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

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

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

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


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


在这里插入图片描述


这篇关于【Unity3D赛车游戏】【四】在Unity中添加阿克曼转向,下压力,质心会让汽车更稳定的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/170506

相关文章

【专题】2024飞行汽车技术全景报告合集PDF分享(附原数据表)

原文链接: https://tecdat.cn/?p=37628 6月16日,小鹏汇天旅航者X2在北京大兴国际机场临空经济区完成首飞,这也是小鹏汇天的产品在京津冀地区进行的首次飞行。小鹏汇天方面还表示,公司准备量产,并计划今年四季度开启预售小鹏汇天分体式飞行汽车,探索分体式飞行汽车城际通勤。阅读原文,获取专题报告合集全文,解锁文末271份飞行汽车相关行业研究报告。 据悉,业内人士对飞行汽车行业

国产游戏崛起:技术革新与文化自信的双重推动

近年来,国产游戏行业发展迅猛,技术水平和作品质量均得到了显著提升。特别是以《黑神话:悟空》为代表的一系列优秀作品,成功打破了过去中国游戏市场以手游和网游为主的局限,向全球玩家展示了中国在单机游戏领域的实力与潜力。随着中国开发者在画面渲染、物理引擎、AI 技术和服务器架构等方面取得了显著进展,国产游戏正逐步赢得国际市场的认可。然而,面对全球游戏行业的激烈竞争,国产游戏技术依然面临诸多挑战,未来的

pip-tools:打造可重复、可控的 Python 开发环境,解决依赖关系,让代码更稳定

在 Python 开发中,管理依赖关系是一项繁琐且容易出错的任务。手动更新依赖版本、处理冲突、确保一致性等等,都可能让开发者感到头疼。而 pip-tools 为开发者提供了一套稳定可靠的解决方案。 什么是 pip-tools? pip-tools 是一组命令行工具,旨在简化 Python 依赖关系的管理,确保项目环境的稳定性和可重复性。它主要包含两个核心工具:pip-compile 和 pip

基于51单片机的自动转向修复系统的设计与实现

文章目录 前言资料获取设计介绍功能介绍设计清单具体实现截图参考文献设计获取 前言 💗博主介绍:✌全网粉丝10W+,CSDN特邀作者、博客专家、CSDN新星计划导师,一名热衷于单片机技术探索与分享的博主、专注于 精通51/STM32/MSP430/AVR等单片机设计 主要对象是咱们电子相关专业的大学生,希望您们都共创辉煌!✌💗 👇🏻 精彩专栏 推荐订阅👇🏻 单片机

跨系统环境下LabVIEW程序稳定运行

在LabVIEW开发中,不同电脑的配置和操作系统(如Win11与Win7)可能对程序的稳定运行产生影响。为了确保程序在不同平台上都能正常且稳定运行,需要从兼容性、驱动、以及性能优化等多个方面入手。本文将详细介绍如何在不同系统环境下,使LabVIEW开发的程序保持稳定运行的有效策略。 LabVIEW版本兼容性 LabVIEW各版本对不同操作系统的支持存在差异。因此,在开发程序时,尽量使用

火柴游戏java版

代码 /*** 火柴游戏* <p>* <li>有24根火柴</li>* <li>组成 A + B = C 等式</li>* <li>总共有多少种适合方式?</li>* <br>* <h>分析:</h>* <li>除去"+"、"="四根,最多可用火柴根数20根。</li>* <li>全部用两根组合成"1",最大数值为1111。使用枚举法,A和B范围在0~1111,C为A+B。判断</li>** @

Unity3D自带Mouse Look鼠标视角代码解析。

Unity3D自带Mouse Look鼠标视角代码解析。 代码块 代码块语法遵循标准markdown代码,例如: using UnityEngine;using System.Collections;/// MouseLook rotates the transform based on the mouse delta./// Minimum and Maximum values can

Unity3D 运动之Move函数和translate

CharacterController.Move 移动 function Move (motion : Vector3) : CollisionFlags Description描述 A more complex move function taking absolute movement deltas. 一个更加复杂的运动函数,每次都绝对运动。 Attempts to

国产游戏行业的崛起与挑战:技术创新引领未来

国产游戏行业的崛起与挑战:技术创新引领未来 近年来,国产游戏行业蓬勃发展,技术水平不断提升,许多优秀作品在国际市场上崭露头角。从画面渲染到物理引擎,从AI技术到服务器架构,国产游戏已实现质的飞跃。然而,面对全球游戏市场的激烈竞争,国产游戏技术仍然面临诸多挑战。本文将探讨这些挑战,并展望未来的机遇,深入分析IT技术的创新将如何推动行业发展。 国产游戏技术现状 国产游戏在画面渲染、物理引擎、AI

第四次北漂----挣个独立游戏的素材钱

第四次北漂,在智联招聘上,有个小公司主动和我联系。面试了下,决定入职了,osg/osgearth的。月薪两万一。 大跌眼镜的是,我入职后,第一天的工作内容就是接手他的工作,三天后他就离职了。 我之所以考虑入职,是因为 1,该公司有恒歌科技的freex平台源码,可以学学,对以前不懂的解解惑。 2,挣点素材钱,看看张亮002的视频,他用了6000多,在虚幻商城买的吸血鬼游戏相关的素材,可以玩两年。我