!在這里插入圖片描述
?????個(gè)人主頁(yè):@元宇宙-秩沅
????? hallo 歡迎 點(diǎn)贊?? 收藏? 留言?? 加關(guān)注?!
????? 本文由 秩沅 原創(chuàng)
????? 收錄于專欄:Unity游戲demo
????Unity3D賽車游戲?
?前言?
–
??????版本: Unity2021
??????適合人群:Unity初學(xué)者
??????學(xué)習(xí)目標(biāo):3D賽車游戲的基礎(chǔ)制作
??????技能掌握:
??(A)車輛優(yōu)化——阿克曼轉(zhuǎn)向添加
??????認(rèn)識(shí)阿克曼轉(zhuǎn)向
引用:阿克曼轉(zhuǎn)向是一種現(xiàn)代汽車的轉(zhuǎn)向方式,也是移動(dòng)機(jī)器人的一種運(yùn)動(dòng)模式,在汽車轉(zhuǎn)彎的時(shí)候,內(nèi)外輪轉(zhuǎn)過(guò)的角度不一樣,內(nèi)側(cè)輪胎轉(zhuǎn)彎半徑小于外側(cè)輪胎
原理圖:
_____________
簡(jiǎn)單理解:一個(gè)桿子把左輪和右輪連接起來(lái)一起轉(zhuǎn)。
左輪的旋轉(zhuǎn)的半徑小于右輪
優(yōu)點(diǎn):大大減小了車輪轉(zhuǎn)向需要的空間,轉(zhuǎn)向更加穩(wěn)定
- 阿克曼公式:
β為汽車前外輪轉(zhuǎn)角,α為汽車前內(nèi)輪轉(zhuǎn)角,K為兩主銷中心距,L為軸距。
??????區(qū)別:
-
未添加阿克曼轉(zhuǎn)向之前的原理:
通過(guò)控制輪子的最大轉(zhuǎn)向范圍來(lái)轉(zhuǎn)向
-
添加之后
更穩(wěn)定,機(jī)動(dòng)性更強(qiáng)
??????關(guān)鍵代碼
- 后輪距尺寸設(shè)置為1.5f ,軸距設(shè)置為2.55f ,radius 默認(rèn)為6,radius 越大旋轉(zhuǎn)的角度看起來(lái)越小
if (horizontal > 0 ) {
//后輪距尺寸設(shè)置為1.5f ,軸距設(shè)置為2.55f ,radius 默認(rèn)為6,radius 越大旋轉(zhuǎn)的角度看起來(lái)越小
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;
//-------------------------------------
//—————————————————————————————————————
//___________項(xiàng)目: ______________
//___________功能: 車輪的運(yùn)動(dòng)
//___________創(chuàng)建者:_______秩沅________
//_____________________________________
//-------------------------------------
//驅(qū)動(dòng)模式的選擇
public enum EDriveType
{
frontDrive, //前輪驅(qū)動(dòng)
backDrive, //后輪驅(qū)動(dòng)
allDrive //四驅(qū)
}
public class WheelMove : MonoBehaviour
{
//-------------------------------------------
//四個(gè)輪子的碰撞器
public WheelCollider[] wheels ;
//網(wǎng)格的獲取
public GameObject[] wheelMesh;
//扭矩力度
public float motorflaot = 200f;
//初始化三維向量和四元數(shù)
private Vector3 wheelPosition = Vector3.zero;
private Quaternion wheelRotation = Quaternion.identity;
//-------------------------------------------
//驅(qū)動(dòng)模式選擇 _默認(rèn)前驅(qū)
public EDriveType DriveType = EDriveType.frontDrive;
//輪半徑
public float radius = 0.25f;
private void FixedUpdate()
{
WheelsAnimation(); //車輪動(dòng)畫
VerticalContorl(); //驅(qū)動(dòng)管理
HorizontalContolr(); //轉(zhuǎn)向管理
}
//垂直軸方向管理(驅(qū)動(dòng)管理)
public void VerticalContorl()
{
switch (DriveType)
{
case EDriveType.frontDrive:
//選擇前驅(qū)
if (InputManager.InputManagerment.vertical != 0) //當(dāng)按下WS鍵時(shí)生效
{
for (int i = 0; i < wheels.Length - 2; i++)
{
//扭矩力度
wheels[i].motorTorque = InputManager.InputManagerment.vertical *(motorflaot / 2); //扭矩馬力歸半
}
}
break;
case EDriveType.backDrive:
//選擇后驅(qū)
if (InputManager.InputManagerment.vertical != 0) //當(dāng)按下WS鍵時(shí)生效
{
for (int i = 2; i < wheels.Length; i++)
{
//扭矩力度
wheels[i].motorTorque = InputManager.InputManagerment.vertical * (motorflaot / 2); //扭矩馬力歸半
}
}
break;
case EDriveType.allDrive:
//選擇四驅(qū)
if (InputManager.InputManagerment.vertical != 0) //當(dāng)按下WS鍵時(shí)生效
{
for (int i = 0; i < wheels.Length; i++)
{
//扭矩力度
wheels[i].motorTorque = InputManager.InputManagerment.vertical * ( motorflaot / 4 ); //扭矩馬力/4
}
}
break;
default:
break;
}
}
//水平軸方向管理(轉(zhuǎn)向管理)
public void HorizontalContolr()
{
if (InputManager.InputManagerment.horizontal > 0)
{
//后輪距尺寸設(shè)置為1.5f ,軸距設(shè)置為2.55f ,radius 默認(rèn)為6,radius 越大旋轉(zhuǎn)的角度看起來(lái)越小
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;
}
}
//車輪動(dòng)畫相關(guān)
public void WheelsAnimation()
{
for (int i = 0; i < wheels.Length ; i++)
{
//獲取當(dāng)前空間的車輪位置 和 角度
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)車輛優(yōu)化——車身持續(xù)穩(wěn)定的優(yōu)化
WheelMove腳本 ——> CarMoveControl腳本 更改腳本名
??????速度屬性實(shí)時(shí)轉(zhuǎn)換
- 每小時(shí)多少公里 和 每秒多少米的對(duì)應(yīng)關(guān)系 ——1m/s = 3.6km/h
速度屬性建議改成Int類型 ,float類型會(huì)上下浮動(dòng)不準(zhǔn)確
//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之間
- 相機(jī)測(cè)速 m/s
//相機(jī)監(jiān)測(cè)實(shí)時(shí)速度
Control = target.GetComponent<CarMoveControl>();
speed = (int )Control.Km_H / 4;
speed = Mathf.Clamp(0, 55,speed ); //對(duì)應(yīng)最大200公里每小時(shí)
- 添加四個(gè)輪子的實(shí)時(shí)速度,對(duì)應(yīng)虛度屬性,可以明顯的觀察四驅(qū)和二驅(qū)的汽車動(dòng)力
//車輛物理屬性相關(guān)
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之間
//顯示每個(gè)輪胎的扭矩
f_right = wheels[0].motorTorque;
f_left = wheels[1].motorTorque;
b_right = wheels[2].motorTorque;
b_left = wheels[3].motorTorque;
}
??????為車子添加下壓力
知識(shí)百科: 什么是下壓力
下壓力是車在行進(jìn)中空氣在車體上下流速不一產(chǎn)生的,使空氣的總壓力指向地面從而增加車的抓地力.
速度越大,下壓力越大,抓地更強(qiáng),越不易翻車
- 關(guān)鍵代碼
//-------------下壓力添加-----------------
//速度越大,下壓力越大,抓地更強(qiáng)
rigidbody.AddForce(-transform.up * downForceValue * rigidbody.velocity .magnitude );
??????質(zhì)心的添加centerMess
知識(shí)百科:什么是質(zhì)心?——質(zhì)量中心
汽車制造商在設(shè)計(jì)汽車時(shí)會(huì)考慮質(zhì)心的位置和重心高度,以盡可能減小質(zhì)心側(cè)偏角。 一些高性能汽車甚至?xí)捎弥鲃?dòng)懸掛系統(tǒng)來(lái)控制車身側(cè)傾,從而減小質(zhì)心側(cè)偏角,提高車輛的穩(wěn)定性和操控性。
質(zhì)量中心越貼下,越不容易翻
//-------------質(zhì)量中心同步----------------
//質(zhì)量中心越貼下,越不容易翻
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;用來(lái)觀看剎車輪胎在滾動(dòng)方向上打滑。加速滑移為負(fù),制動(dòng)滑為正
_______
for (int i = 0; i < slip.Length; i++)
{
WheelHit wheelhit;
wheels[i].GetGroundHit(out wheelhit);
slip[i] = wheelhit.forwardSlip; //輪胎在滾動(dòng)方向上打滑。加速滑移為負(fù),制動(dòng)滑為正
}
??(C)腳本記錄
CarMoveContorl
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//-------------------------------------
//—————————————————————————————————————
//___________項(xiàng)目: ______________
//___________功能: 車輪的運(yùn)動(dòng)
//___________創(chuàng)建者:_______秩沅________
//_____________________________________
//-------------------------------------
//驅(qū)動(dòng)模式的選擇
public enum EDriveType
{
frontDrive, //前輪驅(qū)動(dòng)
backDrive, //后輪驅(qū)動(dòng)
allDrive //四驅(qū)
}
public class CarMoveControl : MonoBehaviour
{
//-------------------------------------------
//四個(gè)輪子的碰撞器
public WheelCollider[] wheels ;
//網(wǎng)格的獲取
public GameObject[] wheelMesh;
//初始化三維向量和四元數(shù)
private Vector3 wheelPosition = Vector3.zero;
private Quaternion wheelRotation = Quaternion.identity;
//-------------------------------------------
//驅(qū)動(dòng)模式選擇 _默認(rèn)前驅(qū)
public EDriveType DriveType = EDriveType.frontDrive;
//----------車輛屬性特征-----------------------
//車剛體
public Rigidbody rigidbody;
//輪半徑
public float radius = 0.25f;
//扭矩力度
public float motorflaot = 8000f;
//剎車力
public float brakVualue = 800000f;
//速度:每小時(shí)多少公里
public int Km_H;
//下壓力
public float downForceValue = 1000f;
//四個(gè)輪胎扭矩力的大小
public float f_right;
public float f_left;
public float b_right;
public float b_left;
//車輪打滑參數(shù)識(shí)別
public float[] slip ;
//質(zhì)心
public Vector3 CenterMass;
//一些屬性的初始化
private void Start()
{
rigidbody = GetComponent<Rigidbody>();
slip = new float[4];
}
private void FixedUpdate()
{
VerticalAttribute();//車輛物理屬性管理
WheelsAnimation(); //車輪動(dòng)畫
VerticalContorl(); //驅(qū)動(dòng)管理
HorizontalContolr(); //轉(zhuǎn)向管理
HandbrakControl(); //手剎管理
}
//車輛物理屬性相關(guān)
public void VerticalAttribute()
{
//---------------速度實(shí)時(shí)---------------
//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之間
//--------------扭矩力實(shí)時(shí)---------------
//顯示每個(gè)輪胎的扭矩
f_right = wheels[0].motorTorque;
f_left = wheels[1].motorTorque;
b_right = wheels[2].motorTorque;
b_left = wheels[3].motorTorque;
//-------------下壓力添加-----------------
//速度越大,下壓力越大,抓地更強(qiáng)
rigidbody.AddForce(-transform.up * downForceValue * rigidbody.velocity .magnitude );
//-------------質(zhì)量中心同步----------------
//質(zhì)量中心越貼下,越不容易翻
rigidbody.centerOfMass = CenterMass;
}
//垂直軸方向運(yùn)動(dòng)管理(驅(qū)動(dòng)管理)
public void VerticalContorl()
{
switch (DriveType)
{
case EDriveType.frontDrive:
//選擇前驅(qū)
if (InputManager.InputManagerment.vertical != 0) //當(dāng)按下WS鍵時(shí)生效
{
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:
//選擇后驅(qū)
if (InputManager.InputManagerment.vertical != 0) //當(dāng)按下WS鍵時(shí)生效
{
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:
//選擇四驅(qū)
if (InputManager.InputManagerment.vertical != 0) //當(dāng)按下WS鍵時(shí)生效
{
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;
}
}
//水平軸方向運(yùn)動(dòng)管理(轉(zhuǎn)向管理)
public void HorizontalContolr()
{
if (InputManager.InputManagerment.horizontal != 0)
{
//后輪距尺寸設(shè)置為1.5f ,軸距設(shè)置為2.55f ,radius 默認(rèn)為6,radius 越大旋轉(zhuǎn)的角度看起來(lái)越小
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; //輪胎在滾動(dòng)方向上打滑。加速滑移為負(fù),制動(dòng)滑為正
}
}
//車輪動(dòng)畫相關(guān)
public void WheelsAnimation()
{
for (int i = 0; i < wheels.Length ; i++)
{
//獲取當(dāng)前空間的車輪位置 和 角度
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;
//-------------------------------------
//—————————————————————————————————————
//___________項(xiàng)目: ______________
//___________功能: 相機(jī)的跟隨
//___________創(chuàng)建者:秩沅_______________
//_____________________________________
//-------------------------------------
public class CameraFllow : MonoBehaviour
{
//目標(biāo)物體
public Transform target;
private CarMoveControl Control;
public int speed;
//鼠標(biāo)滑輪的速度
public float ScrollSpeed = 45f;
//Y軸差距參數(shù)
public float Ydictance = 0f;
public float Ymin = 0f;
public float Ymax = 4f;
//Z軸差距參數(shù)
public float Zdictance = 4f;
public float Zmin = 4f;
public float Zmax = 8f;
//相機(jī)看向的角度 和最終位置
public float angle = -25 ;
public Vector3 lookPosition;
void LateUpdate()
{
//Z軸和Y軸的距離和鼠標(biāo)滑輪聯(lián)系
Ydictance += Input.GetAxis("Mouse ScrollWheel") * ScrollSpeed * Time.deltaTime;//平滑效果
Zdictance += Input.GetAxis("Mouse ScrollWheel") * ScrollSpeed * Time.deltaTime;
//設(shè)置Y軸和x軸的滾輪滑動(dòng)范圍
Ydictance = Mathf.Clamp(Ydictance , Ymin ,Ymax ) ;
Zdictance = Mathf.Clamp(Zdictance , Zmin, Zmax ) ;
//確定好角度,四元數(shù) * 三維向量 = 三維向量
lookPosition = Quaternion.AngleAxis(angle, target .right) * -target.forward ;
//更新位置
transform.position = target.position + Vector3.up * Ydictance - lookPosition * Zdictance ;
//更新角度
transform.rotation = Quaternion.LookRotation(lookPosition);
//實(shí)時(shí)速度
Control = target.GetComponent<CarMoveControl>();
speed = (int )Control.Km_H / 4;
speed = Mathf.Clamp(speed,0, 55 ); //對(duì)應(yīng)最大200公里每小時(shí)
}
}
InputMana
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//-------------------------------------
//—————————————————————————————————————
//___________項(xiàng)目: ______________
//___________功能: 輸入控制管理器
//___________創(chuàng)建者:秩沅_______________
//_____________________________________
//-------------------------------------
public class InputManager : MonoBehaviour
{
//單例模式管理
static private InputManager inputManagerment;
static public InputManager InputManagerment => inputManagerment;
public float horizontal; //水平方向動(dòng)力值
public float vertical; //垂直方向動(dòng)力值
public bool handbanl; //手剎動(dòng)力值
void Awake()
{
inputManagerment = this;
}
void Update()
{
//與Unity中輸入管理器的值相互對(duì)應(yīng)
horizontal = Input.GetAxis("Horizontal");
vertical = Input.GetAxis("Vertical");
handbanl = Input.GetAxis("Jump")!= 0 ? true :false ; //按下空格鍵時(shí)就是1,否則為0
}
}
?????
?【Unityc#專題篇】之c#進(jìn)階篇】
?【Unityc#專題篇】之c#核心篇】
?【Unityc#專題篇】之c#基礎(chǔ)篇】
?【Unity-c#專題篇】之c#入門篇】
?【Unityc#專題篇】—進(jìn)階章題單實(shí)踐練習(xí)
?【Unityc#專題篇】—基礎(chǔ)章題單實(shí)踐練習(xí)
?【Unityc#專題篇】—核心章題單實(shí)踐練習(xí)
你們的點(diǎn)贊?? 收藏? 留言?? 關(guān)注?是我持續(xù)創(chuàng)作,輸出優(yōu)質(zhì)內(nèi)容的最大動(dòng)力!、文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-671762.html
文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-671762.html
到了這里,關(guān)于【Unity3D賽車游戲】【四】在Unity中添加阿克曼轉(zhuǎn)向,下壓力,質(zhì)心會(huì)讓汽車更穩(wěn)定的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!