溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Unity平臺(tái)模擬自動(dòng)擋駕駛汽車的詳細(xì)解析

發(fā)布時(shí)間:2020-07-20 15:36:24 來源:億速云 閱讀:664 作者:小豬 欄目:開發(fā)技術(shù)

這篇文章主要講解了Unity平臺(tái)模擬自動(dòng)擋駕駛汽車的詳細(xì)解析,內(nèi)容清晰明了,對(duì)此有興趣的小伙伴可以學(xué)習(xí)一下,相信大家閱讀完之后會(huì)有幫助。

自動(dòng)擋汽車功能分析:

(1)剎車數(shù)值用連續(xù)量0-255表示,連續(xù)量根據(jù)鍵盤按鍵按下時(shí)長(zhǎng)進(jìn)行遞增,1秒后達(dá)到峰值,無論車輛處于前進(jìn)擋還是倒擋,踩下剎車后車輛逐漸減速至0
(2)汽車分為四個(gè)擋位,停車擋P,倒擋R,空擋N,前進(jìn)擋D
(3)汽車啟動(dòng)后,松開剎車,車輛進(jìn)入怠速模式,速度從0逐步提升至12KM/H
(4)剎車數(shù)值用連續(xù)量0-255表示。車速對(duì)應(yīng)1檔0-10,2檔11-20,3檔21-40,4檔41-60,5檔61-80,6檔81-最大值,對(duì)應(yīng)峰值車速150KM/H
(5)掛住P檔,拉起手剎車輛停止。
(6)掛住R檔,車輛可進(jìn)行倒車操作。
(7)通過鍵盤A和D可以控制車輛左右轉(zhuǎn)向

運(yùn)行結(jié)果圖:

啟動(dòng)車輛,拉起手剎,掛前進(jìn)擋,車輛進(jìn)入怠速模式,緩慢進(jìn)行加速。

Unity平臺(tái)模擬自動(dòng)擋駕駛汽車的詳細(xì)解析

速度提升到12km/h后勻速行駛,繼續(xù)加速需要踩下油門。

Unity平臺(tái)模擬自動(dòng)擋駕駛汽車的詳細(xì)解析

踩下油門后車輛快速加速,自行切換擋位:

Unity平臺(tái)模擬自動(dòng)擋駕駛汽車的詳細(xì)解析

前進(jìn)時(shí)踩下剎車后車子逐漸減速至0:

Unity平臺(tái)模擬自動(dòng)擋駕駛汽車的詳細(xì)解析

切換至倒擋,踩下油門,車輛后退,踩下剎車,車子逐漸減速至0:

Unity平臺(tái)模擬自動(dòng)擋駕駛汽車的詳細(xì)解析

前進(jìn)時(shí)左右轉(zhuǎn)向:

Unity平臺(tái)模擬自動(dòng)擋駕駛汽車的詳細(xì)解析

倒擋時(shí)左右轉(zhuǎn)型:

Unity平臺(tái)模擬自動(dòng)擋駕駛汽車的詳細(xì)解析

源代碼:

采用manager of manager的方式,使用了單例模式。

1.Car_Mng類負(fù)責(zé)管理車輛的物理仿真
2.Input_Mng類負(fù)責(zé)接受用戶的鍵盤輸入信息
3.UI_Mng類負(fù)責(zé)更新UI界面的顯示

Car_Mng

using System.Collections;
using System.Collections.Generic;
using System.Diagnostics.Tracing;
using UnityEngine;

public class Car_Mng : MonoBehaviour
{ 
 static public Car_Mng Instance;
 public SpeedGear speedGear;

 public float maxMotorTorque; //最大的前進(jìn)力矩
 public float maxSpeed; //車輛最大前進(jìn)速度

 public float maxReversMotorTorque; //最大的倒車力矩

 public float maxBrakeToeque; //最大的剎車阻力

 public float maxSteeringAngle; //主動(dòng)輪最大的旋轉(zhuǎn)角度

 public Rigidbody car; //車輛的剛體
 public WheelCollider[] coliders; //車輪碰撞器
 public GameObject[] wheelMesh; //車輪模型


 public CarState carState=CarState.Off; //車輛啟動(dòng)狀態(tài)
 public GearState gearState = GearState.ParkingGear; //車輛的擋位
 public bool isHandBrakeON; //是否拉起手剎的標(biāo)志位

 public float currentSpeed=0; //計(jì)算當(dāng)前車輛的速度

 private bool currentHandBrakeState=true;

 private void Awake()
 {
 Instance = this;
 }
 void Start()
 {
 /* coliders[0].steerAngle = 30;
 coliders[1].steerAngle = 30;
 for (int i = 0; i < 4; i++)
 {
  Quaternion quat;
  Vector3 position;
  coliders[i].GetWorldPose(out position, out quat);
  Debug.Log(position);
  Debug.Log(quat.eulerAngles);
  wheelMesh[i].transform.position = position;
  wheelMesh[i].transform.rotation = 
  coliders[i].transform.rotation * Quaternion.Euler(0, coliders[i].steerAngle, 0); 
  
 }*/
 }

 private void Update()
 {
 UpdateHandBrokeState(); //更新手剎狀態(tài)
 }
 private void FixedUpdate()
 {
 if (gearState == GearState.ForwardGear || gearState == GearState.ReversGear)
 {
  BrakeCalculate(); //剎車計(jì)算 阻力 
  AccCalculate(); //油門計(jì)算 動(dòng)力
 }
 SteerCalculate();
 UpdateCarSpeed(); //更新車子的速度
 AutoChangeGear(); //自動(dòng)換擋 自動(dòng)擋的車子
 SynchronousWheelMesh(); //將車輪的狀態(tài)同步給車的模型
 
 
 }
 void SynchronousWheelMesh()
 {
 for (int i = 0; i < 6; i++)
 {
  Quaternion quat;
  Vector3 position;
  coliders[i].GetWorldPose(out position, out quat);

  wheelMesh[i].transform.position = position;
  wheelMesh[i].transform.rotation = quat;
 }
 }


 void UpdateHandBrokeState()
 {
 if (currentHandBrakeState != isHandBrakeON)
 {
  currentHandBrakeState = isHandBrakeON;
  if (currentHandBrakeState)
  {
  PullupHandbrake();
  }
  else
  {
  PullDownHandbrake();
  }
 }
 } //更新手剎狀態(tài)

 public void StartCar() //啟動(dòng)車輛
 {
 carState = CarState.On;
 }
 public void StopCar() //停車
 {
 carState = CarState.Off; //停止接收油門、方向盤、剎車信號(hào)
 gearState = GearState.ParkingGear; //掛上停車擋
 PullupHandbrake(); //拉起手剎
 }
 void PullupHandbrake() //拉起手剎,相當(dāng)于阻力矩最大,直接Freeze車輛剛體的運(yùn)動(dòng)
 {
 isHandBrakeON = true; //設(shè)置標(biāo)志位
 //僅保留y軸向的運(yùn)動(dòng)
 car.constraints = RigidbodyConstraints.FreezeRotation 
  | RigidbodyConstraints.FreezePositionX | RigidbodyConstraints.FreezePositionZ;
 }

 void PullDownHandbrake() //放下手剎,解鎖運(yùn)動(dòng)
 {
 isHandBrakeON = false;
 //解鎖所有運(yùn)動(dòng)
 car.constraints = RigidbodyConstraints.None;
 }

 
 void BrakeCalculate() //計(jì)算剎車的阻力
 {
 
 var value = Input_Mng.Instance.GetBrakeValue(); //讀取剎車阻力
 var brakeToequePerWheel = maxBrakeToeque / 2 * value / 255; //計(jì)算一個(gè)車輪的阻力
 coliders[0].motorTorque = 0;
 coliders[1].motorTorque = 0;
 for (int i = 0; i < 6; i++)
 {
  coliders[i].brakeTorque = brakeToequePerWheel;
 }
 
 // Debug.Log("剎車阻力:"+ brakeToequePerWheel);
 }

 void AccCalculate() //油門動(dòng)力計(jì)算
 { 
 if (gearState == GearState.ForwardGear) //前進(jìn)
 {  
  var value = Input_Mng.Instance.GetAcceleratorValue();
  if (value != 0) //加速行駛
  {
  
  if(MeterPerSeconds2KmPerHour(currentSpeed) <= 150)
  {
   var accToequePerWheel = maxMotorTorque * value / 255; //計(jì)算一個(gè)車輪的動(dòng)力
   coliders[0].motorTorque = accToequePerWheel;
   coliders[1].motorTorque = accToequePerWheel;
  }
  else //不能超過速度上限
  {
   coliders[0].motorTorque = 0;
   coliders[1].motorTorque = 0;
  }
  }
  else //怠速駕駛
  {
  if (MeterPerSeconds2KmPerHour(currentSpeed) < 12)
  {
   coliders[0].motorTorque = 100;
   coliders[1].motorTorque = 100;
  }
  else
  {
   Debug.Log("無動(dòng)力");
   for (int i = 0; i < 6; i++)
   {
   coliders[i].motorTorque = 0;
   }
  }
  
  }
  
 }
 else //倒車
 {  
  var value = Input_Mng.Instance.GetAcceleratorValue();
  var accToequePerWheel = maxReversMotorTorque / 2 * value / 255; //計(jì)算一個(gè)車輪的動(dòng)力
  coliders[0].motorTorque = -accToequePerWheel;
  coliders[1].motorTorque = -accToequePerWheel;
 }
  
 }


 void SteerCalculate() //計(jì)算轉(zhuǎn)向
 {
 var value= Input_Mng.Instance.GetSteerValue();
 var steerAngle = (value - 128) / 128 * maxSteeringAngle; //計(jì)算旋轉(zhuǎn)角度
 coliders[0].steerAngle = steerAngle;
 coliders[1].steerAngle = steerAngle;

 }


 void AutoChangeGear() //自動(dòng)擋,前進(jìn)時(shí)根據(jù)車輛的速度自動(dòng)切換擋位
 {
 if (gearState == GearState.ForwardGear)
 {
  var speed = MeterPerSeconds2KmPerHour(currentSpeed);
  if (speed <= 10 && speed > 0)
  {
  speedGear = SpeedGear.Speed01;
  }
  if (speed <= 20 && speed > 10)
  {
  speedGear = SpeedGear.Speed02;
  }
  if (speed <= 40 && speed > 20)
  {
  speedGear = SpeedGear.Speed03;
  }
  if (speed <= 60 && speed > 40)
  {
  speedGear = SpeedGear.Speed04;
  }
  if (speed <= 80 && speed > 60)
  {
  speedGear = SpeedGear.Speed05;
  }
  if (speed <= 155 && speed > 80)
  {
  speedGear = SpeedGear.Speed06;
  }
 }
 else
 {
  speedGear = SpeedGear.none;
 }
 
 }

 void UpdateCarSpeed()
 {
 currentSpeed = car.velocity.magnitude;
 }
 static public float MeterPerSeconds2KmPerHour(float speed) //切換單位 m/s換算成 km/h
 {
 return speed*3.6f;
 }
 static float KmPerHour2MeterPerSeconds(float speed) //切換單位 km/h換算成m/s
 {
 return speed/3.6f;
 }

}
public enum CarState
{
 Off = 0, //關(guān)機(jī)狀態(tài)
 On = 1, //運(yùn)行狀態(tài)

}
public enum GearState
{
 ParkingGear = 1, //停車擋
 ReversGear = 2, //倒擋
 NeutralGear = 3, //空擋
 ForwardGear = 4,  //前進(jìn)擋
}

public enum SpeedGear
{
 none,
 Speed01,
 Speed02,
 Speed03,
 Speed04,
 Speed05,
 Speed06
}

Input_Mng

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Input_Mng : MonoBehaviour
{
 static public Input_Mng Instance; //單例模式

 private KeyCode braKeyCode=KeyCode.M; //剎車對(duì)應(yīng)的鍵盤按鍵
 public float brakeValue = 0; //剎車值
 public bool isBra = false;


 private KeyCode accKeyCode=KeyCode.W; //油門對(duì)應(yīng)的鍵盤按鍵
 public float acceleratorValue = 0; //油門值
 public bool isAcc = false;

 private KeyCode leftSteerKeyCode = KeyCode.A;
 private KeyCode rightSteerKeyCode = KeyCode.D;
 public float steerValue = 128;

 private KeyCode parkingKeyCode = KeyCode.Alpha1; //停車對(duì)應(yīng)的按鍵
 private KeyCode reversKeyCode = KeyCode.Alpha2; //倒車對(duì)應(yīng)的按鍵
 private KeyCode neutralKeyCode = KeyCode.Alpha3; //空擋對(duì)應(yīng)的按鍵
 private KeyCode forwardKeyCode = KeyCode.Alpha4; //前進(jìn)擋對(duì)應(yīng)的按鍵

 private KeyCode handBrakeKeyCode = KeyCode.H; //手剎對(duì)應(yīng)的按鍵

 public float GetBrakeValue() //獲取剎車值
 {
 return brakeValue;
 }
 public float GetAcceleratorValue() //獲取油門值
 {
 return acceleratorValue;
 }
 public float GetSteerValue()
 {
 return steerValue;
 } //獲取轉(zhuǎn)彎值

 private void Awake()
 {
 Instance = this;
 }

 private void Update()
 {
 if (Car_Mng.Instance.carState == CarState.On) //當(dāng)車輛啟動(dòng)后,檢測(cè)油門剎車和擋位變換
 {
  
  UpdateGeerState();
  
 }
 UpdateSteerValue();
 UpdateHandBrakeState();
 UpdateAcceleratorValue(accKeyCode);
 UpdateBrakeValue(braKeyCode);
 }
 void UpdateHandBrakeState()
 {
 if (Input.GetKeyDown(handBrakeKeyCode))
 {
  if (Car_Mng.Instance.isHandBrakeON)
  {
  Car_Mng.Instance.isHandBrakeON = false;
  }
  else
  {
  Car_Mng.Instance.isHandBrakeON = true;
  }
 }
 }

 void UpdateAcceleratorValue(KeyCode AccCode)
 {
 if (Input.GetKey(AccCode))
 {
  acceleratorValue += 255 * Time.deltaTime;
  acceleratorValue = Mathf.Clamp(acceleratorValue, 0, 255);
  isAcc = true;
 }
 else
 {
  acceleratorValue = 0;
  isAcc = false;
 }
 } //更新油門狀態(tài)

 void UpdateBrakeValue(KeyCode BraCode) //更新剎車狀態(tài)
 {
 if (Input.GetKey(BraCode))
 {
  brakeValue += 255 * Time.deltaTime;
  brakeValue = Mathf.Clamp(brakeValue, 0, 255);
  isBra = true;
 }
 else
 {
  brakeValue = 0;
  isBra = false;
 }
 }

 void UpdateSteerValue() //更新方向盤狀態(tài)
 {
 if (Input.GetKey(leftSteerKeyCode))
 {
  steerValue -= 255 * Time.deltaTime; //0.5秒左側(cè)打死
  steerValue = Mathf.Clamp(steerValue, 0, 255);
 }else if(Input.GetKey(rightSteerKeyCode))
 {
  steerValue += 255 * Time.deltaTime; //0.5秒右側(cè)打死
  steerValue = Mathf.Clamp(steerValue, 0, 255);
 }
 else
 {
  steerValue = 128;
 }
 }
 void UpdateGeerState() //更新?lián)跷粻顟B(tài)
 {
 if (Input.GetKeyDown(parkingKeyCode)) //設(shè)置為停車檔
 {
  Car_Mng.Instance.gearState = GearState.ParkingGear;
 }
 if (Input.GetKeyDown(reversKeyCode)) //倒車檔
 {
  Car_Mng.Instance.gearState = GearState.ReversGear;
 }
 if (Input.GetKeyDown(neutralKeyCode)) //空擋
 {
  Car_Mng.Instance.gearState = GearState.NeutralGear;
 }
 if (Input.GetKeyDown(forwardKeyCode)) //前進(jìn)擋
 {
  Car_Mng.Instance.gearState = GearState.ForwardGear;
 }

 }
}

UI_Mng

using System.Collections;
using System.Collections.Generic;
using System.Drawing;
using UnityEngine;
using UnityEngine.UI;

public class UI_Mng : MonoBehaviour
{
 static public UI_Mng Instance;

 public Image ParkingBg; //停車檔
 public Image ForwardBg; //前進(jìn)擋
 public Image NeutralBg; //空擋
 public Image ReversBg; //倒車檔
 public Image HandBrakeBg; //手剎
 public Text speedText; //速度顯示
 public Text speedGearText; //擋位顯示

 public Image SwitchBg; //開關(guān)背景
 public Text Switchtext; //開關(guān)顯示文字

 public Image AccBg; //油門
 public Image BraBg; //剎車

 private GearState currentGearState;
 private bool currentBrakeState;

 private void Awake()
 {
 Instance = this;
 }
 private void Update()
 {
 UpdateGearUI();
 UpdateHandBrakeUI();
 UpdateAccBra();
 UpdateSpeed();
 }

 void UpdateSpeed()
 {
 speedText.text = Car_Mng.MeterPerSeconds2KmPerHour(Car_Mng.Instance.currentSpeed).ToString("F2")
  + " Km/h";
 SpeedGear speedGear = Car_Mng.Instance.speedGear;
 switch (speedGear)
 {
  case SpeedGear.none:
  speedGearText.text = "自動(dòng)擋";
  break;
  case SpeedGear.Speed01:
  speedGearText.text = "1擋";
  break;
  case SpeedGear.Speed02:
  speedGearText.text = "2擋";
  break;
  case SpeedGear.Speed03:
  speedGearText.text = "3擋";
  break;
  case SpeedGear.Speed04:
  speedGearText.text = "4擋";
  break;
  case SpeedGear.Speed05:
  speedGearText.text = "5擋";
  break;
  case SpeedGear.Speed06:
  speedGearText.text = "6擋";
  break;
  default:
  break;
 }
 }
 void UpdateAccBra()
 {
 if (Input_Mng.Instance.isAcc)
 {
  AccBg.color = UnityEngine.Color.green;
 }
 else
 {
  AccBg.color = UnityEngine.Color.white;
 }
 if (Input_Mng.Instance.isBra)
 {
  BraBg.color = UnityEngine.Color.green;
 }
 else
 {
  BraBg.color = UnityEngine.Color.white;
 }
 }

 void UpdateHandBrakeUI()
 {
 if (currentBrakeState != Car_Mng.Instance.isHandBrakeON)
 {
  currentBrakeState = Car_Mng.Instance.isHandBrakeON;
  if (currentBrakeState)
  {
  HandBrakeBg.color = UnityEngine.Color.red;
  }
  else
  {
  HandBrakeBg.color = UnityEngine.Color.white;

  }
 }
 }

 private void Start()
 {
 Car_Mng.Instance.StopCar(); //關(guān)閉車輛
 OnCarShutDown();//更新UI 
 }

 void UpdateGearUI()
 {
 if (currentGearState != Car_Mng.Instance.gearState)
 {
  currentGearState = Car_Mng.Instance.gearState;
  ClearGearUI();
  SetGearUI(currentGearState);
 }
 }
 void ClearGearUI()
 {
 ParkingBg.color = UnityEngine.Color.white;
 ForwardBg.color = UnityEngine.Color.white;
 NeutralBg.color = UnityEngine.Color.white;
 ReversBg.color = UnityEngine.Color.white;
 }
 void SetGearUI(GearState state)
 {
 switch (state)
 {
  case GearState.ForwardGear:
  ForwardBg.color = UnityEngine.Color.red;
  break;
  case GearState.ReversGear:
  ReversBg.color = UnityEngine.Color.red;
  break;
  case GearState.NeutralGear:
  NeutralBg.color = UnityEngine.Color.red;
  break;
  case GearState.ParkingGear:
  ParkingBg.color = UnityEngine.Color.red;
  break;

 }
 }


 public void ChangeCarState()
 {
 if (Car_Mng.Instance.carState == CarState.On) //如果處于開機(jī)狀態(tài),則停機(jī)
 {
  Car_Mng.Instance.StopCar(); //關(guān)閉車輛
  OnCarShutDown();//更新UI  

 }else 
 {
  Car_Mng.Instance.StartCar(); //啟動(dòng)車子
  OnCarStart();//更新UI
 }
 }
 private void OnCarStart() //車輛啟動(dòng)時(shí)更新ui
 {
 SwitchBg.color = UnityEngine.Color.red;
 Switchtext.text = "關(guān)閉車輛";
 
 }
 private void OnCarShutDown() //車輛關(guān)閉時(shí)執(zhí)行的邏輯
 {

 SwitchBg.color = UnityEngine.Color.green;
 Switchtext.text = "啟動(dòng)車輛";
 }
 

}

看完上述內(nèi)容,是不是對(duì)Unity平臺(tái)模擬自動(dòng)擋駕駛汽車的詳細(xì)解析有進(jìn)一步的了解,如果還想學(xué)習(xí)更多內(nèi)容,歡迎關(guān)注億速云行業(yè)資訊頻道。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI