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] privatefloatmotorTorque=200f;
floatverticalInput=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] privatefloatmaxSteerAngle=45f;
floathorizontalInput=Input.GetAxisRaw("Horizontal"); //转向flWheelCollider.steerAngle=horizontalInput*maxSteerAngle; frWheelCollider.steerAngle=horizontalInput*maxSteerAngle;
steerAngle仅仅是Wheel Collider的转向角度,还需要调整车轮实际模型的转向角度:
//车轮模型转向flWheelCollider.transform.localEulerAngles=newVector3(0f, flWheelCollider.steerAngle, 0f); frWheelCollider.transform.localEulerAngles=newVector3(0f, frWheelCollider.steerAngle, 0f);
7.通过brakeTorque属性实现刹车制动功能,假设按下Space空格键时进行刹车:
//刹车boolisBraking=Input.GetKey(KeyCode.Space); rlWheelCollider.brakeTorque=isBraking?brakeTorque : 0f; rrWheelCollider.brakeTorque=isBraking?brakeTorque : 0f;
8.还要注意Rigybody组件的centerOfMass位置需要设为车身的底部:
最终代码:
usingUnityEngine; publicclassVehicleController : MonoBehaviour{ [SerializeField] privateWheelColliderflWheelCollider; [SerializeField] privateWheelColliderfrWheelCollider; [SerializeField] privateWheelColliderrlWheelCollider; [SerializeField] privateWheelColliderrrWheelCollider; [SerializeField] privateTransformflWheelTransform; [SerializeField] privateTransformfrWheelTransform; [SerializeField] privateTransformrlWheelTransform; [SerializeField] privateTransformrrWheelTransform; [SerializeField] privateTransformcenterOfMass; [SerializeField] privatefloatmotorTorque=200f; [SerializeField] privatefloatbrakeTorque=200f; [SerializeField] privatefloatmaxSteerAngle=45f; privatevoidStart() { GetComponent<Rigidbody>().centerOfMass=centerOfMass.localPosition; } privatevoidUpdate() { floatverticalInput=Input.GetAxisRaw("Vertical"); floathorizontalInput=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=newVector3(0f, flWheelCollider.steerAngle, 0f); frWheelCollider.transform.localEulerAngles=newVector3(0f, frWheelCollider.steerAngle, 0f); //刹车boolisBraking=Input.GetKey(KeyCode.Space); rlWheelCollider.brakeTorque=isBraking?brakeTorque : 0f; rrWheelCollider.brakeTorque=isBraking?brakeTorque : 0f; } }























