Unity 【Wheel Collider】实现游戏中的车具控制

Wheel Collider专门用于模拟车具轮胎的物理属性,内置了碰撞检测、轮胎摩擦模型等,可以用于实现车具的控制。

  

核心的几个变量:

        motorTorque:驱动力,将其设为正值向前移动,负值向后移动

        brakeTorque:制动力,该值为正

        rpm:车轮转速,注意它是每分钟转动多少圈

        steerAngle:转向角度,可以实现车具的转弯

        mass:车轮的重量,单位kg

        radius:车轮的半径

        forwardFriction:车轮在正向转动时的摩擦力

        sidewaysFriction:车轮在侧向转动时的摩擦力

了解了这几个核心变量后,下面简单实现车具的控制:

1.首先给车具模型添加刚体组件,假设重量为2吨,将Mass设为2000:

2.为每个车轮模型添加一个空父级,添加Wheel Collider组件,假设每个轮胎的重量为20kg:

3.注意Wheel Collider碰撞器不能被车身的碰撞器包裹,否则车子不会移动。另外注意如果没有给车身添加Rigybody组件的话,Scene窗口也是看不到Wheel Collider的。

4.为Wheel Collider添加motorTorque驱动力,声明一个float类型的变量,暂定为200f, 假设车辆为后驱,给两个后轮添加驱动力:

[SerializeField] private float motorTorque = 200f;
float verticalInput = Input.GetAxisRaw("Vertical");
//驱动
rlWheelCollider.motorTorque = verticalInput * motorTorque;
rrWheelCollider.motorTorque = verticalInput * motorTorque;

5.车辆移动时,使车轮模型滚动,滚动的角度通过Wheel Collider组件的rpm属性获取,上面提到该属性代表车轮每分钟转动多少圈,因此我们将其除以60,代表每秒钟转动的圈数,1圈为360度,因此再乘以360即可获得要滚动的角度:

//车轮模型滚动
flWheelTransform.Rotate(flWheelCollider.rpm / 60 * 360 * Time.deltaTime * Vector3.right);
frWheelTransform.Rotate(frWheelCollider.rpm / 60 * 360 * Time.deltaTime * Vector3.right);
rlWheelTransform.Rotate(rlWheelCollider.rpm / 60 * 360 * Time.deltaTime * Vector3.right);
rrWheelTransform.Rotate(rrWheelCollider.rpm / 60 * 360 * Time.deltaTime * Vector3.right);

6.为Wheel Collider添加转向,声明一个float类型变量来限制车轮最大的转动角度:

[SerializeField] private float maxSteerAngle = 45f;
float horizontalInput = Input.GetAxisRaw("Horizontal");
//转向
flWheelCollider.steerAngle = horizontalInput * maxSteerAngle;
frWheelCollider.steerAngle = horizontalInput * maxSteerAngle;

steerAngle仅仅是Wheel Collider的转向角度,还需要调整车轮实际模型的转向角度:

//车轮模型转向
flWheelCollider.transform.localEulerAngles = new Vector3(0f, flWheelCollider.steerAngle, 0f);
frWheelCollider.transform.localEulerAngles = new Vector3(0f, frWheelCollider.steerAngle, 0f);

7.通过brakeTorque属性实现刹车制动功能,假设按下Space空格键时进行刹车:

//刹车
bool isBraking = Input.GetKey(KeyCode.Space);
rlWheelCollider.brakeTorque = isBraking ? brakeTorque : 0f;
rrWheelCollider.brakeTorque = isBraking ? brakeTorque : 0f;

8.还要注意Rigybody组件的centerOfMass位置需要设为车身的底部:

最终代码:

using UnityEngine;

public class VehicleController : MonoBehaviour
{
    [SerializeField] private WheelCollider flWheelCollider;
    [SerializeField] private WheelCollider frWheelCollider;
    [SerializeField] private WheelCollider rlWheelCollider;
    [SerializeField] private WheelCollider rrWheelCollider;

    [SerializeField] private Transform flWheelTransform;
    [SerializeField] private Transform frWheelTransform;
    [SerializeField] private Transform rlWheelTransform;
    [SerializeField] private Transform rrWheelTransform;

    [SerializeField] private Transform centerOfMass;
    [SerializeField] private float motorTorque = 200f;
    [SerializeField] private float brakeTorque = 200f;
    [SerializeField] private float maxSteerAngle = 45f;

    private void Start()
    {
        GetComponent<Rigidbody>().centerOfMass = centerOfMass.localPosition;
    }
    private void Update()
    {
        float verticalInput = Input.GetAxisRaw("Vertical");
        float horizontalInput = Input.GetAxisRaw("Horizontal");

        //驱动
        rlWheelCollider.motorTorque = verticalInput * motorTorque;
        rrWheelCollider.motorTorque = verticalInput * motorTorque;
        //转向
        flWheelCollider.steerAngle = horizontalInput * maxSteerAngle;
        frWheelCollider.steerAngle = horizontalInput * maxSteerAngle;

        //车轮模型转动
        flWheelTransform.Rotate(flWheelCollider.rpm * 360 * Time.deltaTime * Vector3.right);
        frWheelTransform.Rotate(frWheelCollider.rpm * 360 * Time.deltaTime * Vector3.right);
        rlWheelTransform.Rotate(rlWheelCollider.rpm * 360 * Time.deltaTime * Vector3.right);
        rrWheelTransform.Rotate(rrWheelCollider.rpm * 360 * Time.deltaTime * Vector3.right);
        //车轮模型转向
        flWheelCollider.transform.localEulerAngles = new Vector3(0f, flWheelCollider.steerAngle, 0f);
        frWheelCollider.transform.localEulerAngles = new Vector3(0f, frWheelCollider.steerAngle, 0f);

        //刹车
        bool isBraking = Input.GetKey(KeyCode.Space);
        rlWheelCollider.brakeTorque = isBraking ? brakeTorque : 0f;
        rrWheelCollider.brakeTorque = isBraking ? brakeTorque : 0f;
    }
}

  • 10
    点赞
  • 61
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 10
    评论
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CoderZ1010

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值