Unity平台模拟自动挡驾驶汽车
程序员文章站
2022-08-30 12:52:47
自动挡汽车功能分析:(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可以控制车辆左右转向
运行结果图:
启动车辆,拉起手刹,挂前进挡,车辆进入怠速模式,缓慢进行加速。
速度提升到12km/h后匀速行驶,继续加速需要踩下油门。
踩下油门后车辆快速加速,自行切换挡位:
前进时踩下刹车后车子逐渐减速至0:
切换至倒挡,踩下油门,车辆后退,踩下刹车,车子逐渐减速至0:
前进时左右转向:
倒挡时左右转型:
源代码:
采用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 = "启动车辆"; } }
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
上一篇: Android几种多渠道打包的步骤详解
下一篇: 本科毕业生该不该创业?