欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Unity平台模拟自动挡驾驶汽车

程序员文章站 2022-04-11 09:55:14
自动挡汽车功能分析:(1)刹车数值用连续量0-255表示,连续量根据键盘按键按下时长进行递增,1秒后达到峰值,无论车辆处于前进挡还是倒挡,踩下刹车后车辆逐渐减速至0(2)汽车分为四个挡位,停车挡p,倒...

自动挡汽车功能分析:

(1)刹车数值用连续量0-255表示,连续量根据键盘按键按下时长进行递增,1秒后达到峰值,无论车辆处于前进挡还是倒挡,踩下刹车后车辆逐渐减速至0
(2)汽车分为四个挡位,停车挡p,倒挡r,空挡n,前进挡d
(3)汽车启动后,松开刹车,车辆进入怠速模式,速度从0逐步提升至12km/h
(4)刹车数值用连续量0-255表示。车速对应1档0-10,2档11-20,3档21-40,4档41-60,5档61-80,6档81-最大值,对应峰值车速150km/h
(5)挂住p档,拉起手刹车辆停止。
(6)挂住r档,车辆可进行倒车操作。
(7)通过键盘a和d可以控制车辆左右转向

运行结果图:

启动车辆,拉起手刹,挂前进挡,车辆进入怠速模式,缓慢进行加速。

Unity平台模拟自动挡驾驶汽车

速度提升到12km/h后匀速行驶,继续加速需要踩下油门。

Unity平台模拟自动挡驾驶汽车

踩下油门后车辆快速加速,自行切换挡位:

Unity平台模拟自动挡驾驶汽车

前进时踩下刹车后车子逐渐减速至0:

Unity平台模拟自动挡驾驶汽车

切换至倒挡,踩下油门,车辆后退,踩下刹车,车子逐渐减速至0:

Unity平台模拟自动挡驾驶汽车

前进时左右转向:

Unity平台模拟自动挡驾驶汽车

倒挡时左右转型:

Unity平台模拟自动挡驾驶汽车

源代码:

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

1.car_mng类负责管理车辆的物理仿真
2.input_mng类负责接受用户的键盘输入信息
3.ui_mng类负责更新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; //最大的前进力矩
 public float maxspeed; //车辆最大前进速度

 public float maxreversmotortorque; //最大的倒车力矩

 public float maxbraketoeque; //最大的刹车阻力

 public float maxsteeringangle; //主动轮最大的旋转角度

 public rigidbody car; //车辆的刚体
 public wheelcollider[] coliders; //车轮碰撞器
 public gameobject[] wheelmesh; //车轮模型


 public carstate carstate=carstate.off; //车辆启动状态
 public gearstate gearstate = gearstate.parkinggear; //车辆的挡位
 public bool ishandbrakeon; //是否拉起手刹的标志位

 public float currentspeed=0; //计算当前车辆的速度

 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(); //更新手刹状态
 }
 private void fixedupdate()
 {
 if (gearstate == gearstate.forwardgear || gearstate == gearstate.reversgear)
 {
  brakecalculate(); //刹车计算 阻力 
  acccalculate(); //油门计算 动力
 }
 steercalculate();
 updatecarspeed(); //更新车子的速度
 autochangegear(); //自动换挡 自动挡的车子
 synchronouswheelmesh(); //将车轮的状态同步给车的模型
 
 
 }
 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();
  }
 }
 } //更新手刹状态

 public void startcar() //启动车辆
 {
 carstate = carstate.on;
 }
 public void stopcar() //停车
 {
 carstate = carstate.off; //停止接收油门、方向盘、刹车信号
 gearstate = gearstate.parkinggear; //挂上停车挡
 pulluphandbrake(); //拉起手刹
 }
 void pulluphandbrake() //拉起手刹,相当于阻力矩最大,直接freeze车辆刚体的运动
 {
 ishandbrakeon = true; //设置标志位
 //仅保留y轴向的运动
 car.constraints = rigidbodyconstraints.freezerotation 
  | rigidbodyconstraints.freezepositionx | rigidbodyconstraints.freezepositionz;
 }

 void pulldownhandbrake() //放下手刹,解锁运动
 {
 ishandbrakeon = false;
 //解锁所有运动
 car.constraints = rigidbodyconstraints.none;
 }

 
 void brakecalculate() //计算刹车的阻力
 {
 
 var value = input_mng.instance.getbrakevalue(); //读取刹车阻力
 var braketoequeperwheel = maxbraketoeque / 2 * value / 255; //计算一个车轮的阻力
 coliders[0].motortorque = 0;
 coliders[1].motortorque = 0;
 for (int i = 0; i < 6; i++)
 {
  coliders[i].braketorque = braketoequeperwheel;
 }
 
 // debug.log("刹车阻力:"+ braketoequeperwheel);
 }

 void acccalculate() //油门动力计算
 { 
 if (gearstate == gearstate.forwardgear) //前进
 {  
  var value = input_mng.instance.getacceleratorvalue();
  if (value != 0) //加速行驶
  {
  
  if(meterperseconds2kmperhour(currentspeed) <= 150)
  {
   var acctoequeperwheel = maxmotortorque * value / 255; //计算一个车轮的动力
   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("无动力");
   for (int i = 0; i < 6; i++)
   {
   coliders[i].motortorque = 0;
   }
  }
  
  }
  
 }
 else //倒车
 {  
  var value = input_mng.instance.getacceleratorvalue();
  var acctoequeperwheel = maxreversmotortorque / 2 * value / 255; //计算一个车轮的动力
  coliders[0].motortorque = -acctoequeperwheel;
  coliders[1].motortorque = -acctoequeperwheel;
 }
  
 }


 void steercalculate() //计算转向
 {
 var value= input_mng.instance.getsteervalue();
 var steerangle = (value - 128) / 128 * maxsteeringangle; //计算旋转角度
 coliders[0].steerangle = steerangle;
 coliders[1].steerangle = steerangle;

 }


 void autochangegear() //自动挡,前进时根据车辆的速度自动切换挡位
 {
 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, //关机状态
 on = 1, //运行状态

}
public enum gearstate
{
 parkinggear = 1, //停车挡
 reversgear = 2, //倒挡
 neutralgear = 3, //空挡
 forwardgear = 4,  //前进挡
}

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; //刹车对应的键盘按键
 public float brakevalue = 0; //刹车值
 public bool isbra = false;


 private keycode acckeycode=keycode.w; //油门对应的键盘按键
 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; //停车对应的按键
 private keycode reverskeycode = keycode.alpha2; //倒车对应的按键
 private keycode neutralkeycode = keycode.alpha3; //空挡对应的按键
 private keycode forwardkeycode = keycode.alpha4; //前进挡对应的按键

 private keycode handbrakekeycode = keycode.h; //手刹对应的按键

 public float getbrakevalue() //获取刹车值
 {
 return brakevalue;
 }
 public float getacceleratorvalue() //获取油门值
 {
 return acceleratorvalue;
 }
 public float getsteervalue()
 {
 return steervalue;
 } //获取转弯值

 private void awake()
 {
 instance = this;
 }

 private void update()
 {
 if (car_mng.instance.carstate == carstate.on) //当车辆启动后,检测油门刹车和挡位变换
 {
  
  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;
 }
 } //更新油门状态

 void updatebrakevalue(keycode bracode) //更新刹车状态
 {
 if (input.getkey(bracode))
 {
  brakevalue += 255 * time.deltatime;
  brakevalue = mathf.clamp(brakevalue, 0, 255);
  isbra = true;
 }
 else
 {
  brakevalue = 0;
  isbra = false;
 }
 }

 void updatesteervalue() //更新方向盘状态
 {
 if (input.getkey(leftsteerkeycode))
 {
  steervalue -= 255 * time.deltatime; //0.5秒左侧打死
  steervalue = mathf.clamp(steervalue, 0, 255);
 }else if(input.getkey(rightsteerkeycode))
 {
  steervalue += 255 * time.deltatime; //0.5秒右侧打死
  steervalue = mathf.clamp(steervalue, 0, 255);
 }
 else
 {
  steervalue = 128;
 }
 }
 void updategeerstate() //更新挡位状态
 {
 if (input.getkeydown(parkingkeycode)) //设置为停车档
 {
  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)) //前进挡
 {
  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; //前进挡
 public image neutralbg; //空挡
 public image reversbg; //倒车档
 public image handbrakebg; //手刹
 public text speedtext; //速度显示
 public text speedgeartext; //挡位显示

 public image switchbg; //开关背景
 public text switchtext; //开关显示文字

 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 = "自动挡";
  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(); //关闭车辆
 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) //如果处于开机状态,则停机
 {
  car_mng.instance.stopcar(); //关闭车辆
  oncarshutdown();//更新ui  

 }else 
 {
  car_mng.instance.startcar(); //启动车子
  oncarstart();//更新ui
 }
 }
 private void oncarstart() //车辆启动时更新ui
 {
 switchbg.color = unityengine.color.red;
 switchtext.text = "关闭车辆";
 
 }
 private void oncarshutdown() //车辆关闭时执行的逻辑
 {

 switchbg.color = unityengine.color.green;
 switchtext.text = "启动车辆";
 }
 

}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。

相关标签: Unity 驾驶汽车