自动挡汽车功能分析:
(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 = "启动车辆";
}
}
您可能感兴趣的文章:Unity3D实现虚拟按钮控制人物移动效果unity实现手机端摇杆控制人物移动Unity UGUI通过摇杆控制角色移动