【unity实战】简易的车辆控制系统
最终效果
文章目录
- 最终效果
- 前言
- 一、实战
- 1、模型下载
- 2、添加刚体和碰撞体
- 3、提前车辆,并添加WheelCollider组件,配置参数
- 4、车辆移动
- 5、刹车
- 6、转向和车辆重心
- 7、动画化车轮
- 8、相机跟随
- 二、最终车辆控制代码
- 三、车辆引擎声音
- 专栏推荐
- 完结
前言
在游戏开发中,车辆控制系统是一个非常常见且重要的功能模块。无论是赛车游戏、开放世界游戏还是模拟驾驶游戏,一个稳定且真实的车辆控制系统都能大大提升玩家的游戏体验。
本教程将带领大家从零开始,在Unity中实现一个简易但功能完整的车辆控制系统。
这个系统采用了Unity内置的WheelCollider组件来处理车辆物理,相比完全自定义的物理实现更加稳定高效。我们还会学习如何调整车辆的重心、转向灵敏度等参数,使车辆操控感更加真实。
最终我们将得到一个可以自由驾驶的车辆,具备加速、刹车、转向等基本功能,并且车轮会随着运动正确旋转,相机也会智能跟随车辆移动。
让我们开始这个有趣的项目吧!在实现过程中,你可以随时调整参数来获得不同的驾驶体验,找到最适合你游戏的操控感觉。
一、实战
1、模型下载
https://assetstore.unity.com/packages/3d/vehicles/land/1950s-classic-car-6-variant-322054
2、添加刚体和碰撞体
3、提前车辆,并添加WheelCollider组件,配置参数
4、车辆移动
// 车轴枚举
public enum Axel
{Front, // 前轮Rear // 后轮
}// 车轮结构体
[Serializable]
public struct Wheel
{public GameObject wheelModel; // 车轮模型public WheelCollider wheelCollider; // 车轮碰撞器public Axel axel; // 所属车轴
}[SerializeField] public float maxAcceleration = 10.0f; // 最大加速度
public List<Wheel> wheels; // 车轮列表float _moveInput; // 移动输入值private Rigidbody _carRb; // 车辆刚体组件void Start()
{// 获取刚体组件并设置重心_carRb = GetComponent<Rigidbody>();
}void Update()
{GetInputs(); // 获取输入
}void FixedUpdate()
{Move(); // 移动控制
}// 获取输入
void GetInputs()
{_moveInput = Input.GetAxis("Vertical"); // 获取垂直输入
}// 移动控制
void Move()
{foreach (var wheel in wheels){// 设置车轮马达扭矩wheel.wheelCollider.motorTorque = _moveInput * 600 * maxAcceleration;}
}
配置
效果
5、刹车
public float brakeAcceleration = 50.0f; // 刹车加速度void FixedUpdate()
{Move(); // 移动控制Brake(); // 刹车控制
}// 刹车控制
void Brake()
{// 如果按下空格键或没有移动输入if (Input.GetKey(KeyCode.Space) || _moveInput == 0){foreach (var wheel in wheels){// 设置刹车扭矩wheel.wheelCollider.brakeTorque = 300 * brakeAcceleration;}}else{foreach (var wheel in wheels){// 取消刹车扭矩wheel.wheelCollider.brakeTorque = 0;}}
}
效果
6、转向和车辆重心
public float turnSensitivity = 1.0f; // 转向灵敏度
public float maxSteerAngle = 30.0f; // 最大转向角度
public Vector3 centerOfMass; // 车辆重心
float _steerInput; // 转向输入值void Start()
{// 获取刚体组件并设置重心_carRb = GetComponent<Rigidbody>();_carRb.centerOfMass = centerOfMass;
}void FixedUpdate()
{Move(); // 移动控制Brake(); // 刹车控制Steer(); // 转向控制
}// 获取输入
void GetInputs()
{_moveInput = Input.GetAxis("Vertical"); // 获取垂直输入_steerInput = Input.GetAxis("Horizontal"); // 获取水平输入
}// 转向控制
void Steer()
{foreach (var wheel in wheels){// 只对前轮进行转向if (wheel.axel == Axel.Front){var _steerAngle = _steerInput * turnSensitivity * maxSteerAngle;// 平滑过渡转向角度wheel.wheelCollider.steerAngle = Mathf.Lerp(wheel.wheelCollider.steerAngle, _steerAngle, 0.6f);}}
}
效果
7、动画化车轮
void Update()
{GetInputs(); // 获取输入AnimateWheels(); // 动画化车轮
}// 动画化车轮
void AnimateWheels()
{foreach (var wheel in wheels){Quaternion rot;Vector3 pos;// 获取车轮碰撞器的世界位置和旋转wheel.wheelCollider.GetWorldPose(out pos, out rot);// 更新车轮模型的位置和旋转wheel.wheelModel.transform.position = pos;wheel.wheelModel.transform.rotation = rot;}
}
效果
8、相机跟随
参考:【unity知识】最新的Cinemachine3简单使用介绍
效果
二、最终车辆控制代码
using UnityEngine;
using System;
using System.Collections.Generic;public class CarController : MonoBehaviour
{// 车轴枚举public enum Axel{Front, // 前轮Rear // 后轮}// 车轮结构体[Serializable]public struct Wheel{public GameObject wheelModel; // 车轮模型public WheelCollider wheelCollider; // 车轮碰撞器public Axel axel; // 所属车轴}[SerializeField] public float maxAcceleration = 10.0f; // 最大加速度public float brakeAcceleration = 50.0f; // 刹车加速度public float turnSensitivity = 1.0f; // 转向灵敏度public float maxSteerAngle = 30.0f; // 最大转向角度public Vector3 centerOfMass; // 车辆重心public List<Wheel> wheels; // 车轮列表float _moveInput; // 移动输入值float _steerInput; // 转向输入值private Rigidbody _carRb; // 车辆刚体组件void Start(){// 获取刚体组件并设置重心_carRb = GetComponent<Rigidbody>();_carRb.centerOfMass = centerOfMass;}void Update(){GetInputs(); // 获取输入AnimateWheels(); // 动画化车轮}void FixedUpdate(){Move(); // 移动控制Brake(); // 刹车控制Steer(); // 转向控制}// 获取输入void GetInputs(){_moveInput = Input.GetAxis("Vertical"); // 获取垂直输入_steerInput = Input.GetAxis("Horizontal"); // 获取水平输入}// 移动控制void Move(){foreach (var wheel in wheels){// 设置车轮马达扭矩wheel.wheelCollider.motorTorque = _moveInput * 600 * maxAcceleration;}}// 转向控制void Steer(){foreach (var wheel in wheels){// 只对前轮进行转向if (wheel.axel == Axel.Front){var _steerAngle = _steerInput * turnSensitivity * maxSteerAngle;// 平滑过渡转向角度wheel.wheelCollider.steerAngle = Mathf.Lerp(wheel.wheelCollider.steerAngle, _steerAngle, 0.6f);}}}// 刹车控制void Brake(){// 如果按下空格键或没有移动输入if (Input.GetKey(KeyCode.Space) || _moveInput == 0){foreach (var wheel in wheels){// 设置刹车扭矩wheel.wheelCollider.brakeTorque = 300 * brakeAcceleration;}}else{foreach (var wheel in wheels){// 取消刹车扭矩wheel.wheelCollider.brakeTorque = 0;}}}// 动画化车轮void AnimateWheels(){foreach (var wheel in wheels){Quaternion rot;Vector3 pos;// 获取车轮碰撞器的世界位置和旋转wheel.wheelCollider.GetWorldPose(out pos, out rot);// 更新车轮模型的位置和旋转wheel.wheelModel.transform.position = pos;wheel.wheelModel.transform.rotation = rot;}}
}
三、车辆引擎声音
新增脚本,根据速度计算的动态音高
using UnityEngine;public class CarSounds : MonoBehaviour
{[Header("速度参数")]public float maxSpeed = 40f; // 引擎声音最大速度阈值private float currentSpeed; // 当前车辆速度[Header("音频参数")]public float minPitch = 0.2f; // 引擎最小音高 (默认值示例)public float maxPitch = 1f; // 引擎最大音高 (默认值示例)private float pitchFromCar; // 根据速度计算的动态音高private Rigidbody carRb; // 车辆刚体组件private AudioSource carAudio; // 音频源组件void Start(){// 获取组件引用carAudio = GetComponent<AudioSource>();carRb = GetComponent<Rigidbody>();}void Update(){EngineSound(); // 每帧更新引擎声音}/// <summary>/// 根据车速动态调整引擎音效/// </summary>void EngineSound(){// 获取当前速度(忽略垂直方向)currentSpeed = carRb.linearVelocity.magnitude;// 计算速度比例映射到音高范围pitchFromCar = Mathf.Clamp(currentSpeed / maxSpeed, minPitch, maxPitch);carAudio.pitch = pitchFromCar;}
}
专栏推荐
地址 |
---|
【unity游戏开发入门到精通——C#篇】 |
【unity游戏开发入门到精通——unity通用篇】 |
【unity游戏开发入门到精通——unity3D篇】 |
【unity游戏开发入门到精通——unity2D篇】 |
【unity实战】 |
【制作100个Unity游戏】 |
【推荐100个unity插件】 |
【实现100个unity特效】 |
【unity框架/工具集开发】 |
【unity游戏开发——模型篇】 |
【unity游戏开发——InputSystem】 |
【unity游戏开发——Animator动画】 |
【unity游戏开发——UGUI】 |
【unity游戏开发——联网篇】 |
【unity游戏开发——优化篇】 |
【unity游戏开发——shader篇】 |
【unity游戏开发——编辑器扩展】 |
【unity游戏开发——热更新】 |
【unity游戏开发——网络】 |
完结
好了,我是向宇
,博客地址:https://xiangyu.blog.csdn.net,如果学习过程中遇到任何问题,也欢迎你评论私信找我。
赠人玫瑰,手有余香!如果文章内容对你有所帮助,请不要吝啬你的点赞评论和关注
,你的每一次支持
都是我不断创作的最大动力。当然如果你发现了文章中存在错误
或者有更好的解决方法
,也欢迎评论私信告诉我哦!