【unity实战】简易的车辆控制系统

最终效果

文章目录

前言

在游戏开发中,车辆控制系统是一个非常常见且重要的功能模块。无论是赛车游戏、开放世界游戏还是模拟驾驶游戏,一个稳定且真实的车辆控制系统都能大大提升玩家的游戏体验。

本教程将带领大家从零开始,在Unity中实现一个简易但功能完整的车辆控制系统。

这个系统采用了Unity内置的WheelCollider组件来处理车辆物理,相比完全自定义的物理实现更加稳定高效。我们还会学习如何调整车辆的重心、转向灵敏度等参数,使车辆操控感更加真实。

最终我们将得到一个可以自由驾驶的车辆,具备加速、刹车、转向等基本功能,并且车轮会随着运动正确旋转,相机也会智能跟随车辆移动。

让我们开始这个有趣的项目吧!在实现过程中,你可以随时调整参数来获得不同的驾驶体验,找到最适合你游戏的操控感觉。

一、实战

1、模型下载

https://assetstore.unity.com/packages/3d/vehicles/land/1950s-classic-car-6-variant-322054

2、添加刚体和碰撞体

3、提前车辆,并添加WheelCollider组件,配置参数

4、车辆移动

csharp 复制代码
// 车轴枚举
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、刹车

csharp 复制代码
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、转向和车辆重心

csharp 复制代码
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、动画化车轮

csharp 复制代码
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简单使用介绍

效果

二、最终车辆控制代码

csharp 复制代码
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;
        }
    }
}

三、车辆引擎声音

新增脚本,根据速度计算的动态音高

csharp 复制代码
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,如果学习过程中遇到任何问题,也欢迎你评论私信找我。

赠人玫瑰,手有余香!如果文章内容对你有所帮助,请不要吝啬你的点赞评论和关注,你的每一次支持都是我不断创作的最大动力。当然如果你发现了文章中存在错误或者有更好的解决方法,也欢迎评论私信告诉我哦!

相关推荐
摸鱼的春哥1 小时前
10年3次大失败,他从“罪人”输成了中年人的“白月光”
游戏
SmalBox2 小时前
【光照】Unity中的[经验模型]
unity·渲染
大飞pkz3 小时前
【设计模式】C#反射实现抽象工厂模式
设计模式·c#·抽象工厂模式·c#反射·c#反射实现抽象工厂模式
萘柰奈3 小时前
Unity学习----【进阶】TextMeshPro学习(三)--进阶知识点(TMP基础设置,材质球相关,两个辅助工具类)
学习·unity
Yasin Chen4 小时前
Unity UI坐标说明
ui·unity
应用市场5 小时前
无人机姿态控制系统详解与实现
游戏引擎·cocos2d
唐青枫5 小时前
从入门到进阶:C#.NET Stopwatch 计时与性能测量全攻略
c#·.net
陈言必行9 小时前
Unity 性能优化 之 编辑器创建资源优化( 工作流 | 场景 | 预制体)
unity·编辑器·游戏引擎
未来之窗软件服务14 小时前
幽冥大陆(二)RDIFSDK 接口文档:布草洗涤厂高效运营的技术桥梁C#—东方仙盟
开发语言·c#·rdif·仙盟创梦ide·东方仙盟
1uther15 小时前
Unity核心概念⑨:Screen
开发语言·游戏·unity·c#·游戏引擎