很多游戏中有着像汽车等交通工具,在Unity内置的物理引擎可以帮助开发者进行设计开发。在Unity中通过车轮碰撞器来控制车轮运动,以实现车轮带动汽车行驶的效果。
车轮碰撞器的添加方法与其他碰撞器的添加方法不同,车轮碰撞器一般不直接添加到车轮游戏对象上,而是添加交通工具游戏对象的子对象目录中新建的空对象上,然后将此空对象的位置调整到与车轮位置相同。
车轮碰撞器的特性
Mass
车轮的重力
Radius
车轮的半径
Wheel Damping Rate
车轮旋转阻尼
Suspension Distance
悬挂高度,可提高车辆稳定性,不小于0且方向垂直向下
Force App Point Distance
悬挂力应用点
Center
基于模型坐标系的车轮碰撞器的中心点
Spring
达到目标中心的弹力,值越大到达中心越快
Damper
悬浮速度的阻尼,值越大车辆归位所消耗的时间越长
Target Position
悬挂中心
Forward——前向 Sideways——侧向
Extremum Slip
摩擦曲线滑动极值
Extremum Point
摩擦曲线的极值点
Asymptote Slip
渐进线的滑动值
Asymptote Point
曲线的渐进线点
Stiffness
刚度,控制侧向摩擦曲线的倍数
交通工具的构成
F1为空对象
Wheel为空对象
WheelCollider为空对象
脚本构成
Car.cs 将脚本挂载在F1上,通过摇杆来控制汽车
public class Car : MonoBehaviour {
public WheelCollider FLCollider;//声明车前左侧车轮碰撞器
public WheelCollider FRCollider;//声明车前右侧车轮碰撞器
public EasyJoystick myJoystick;//声明虚拟摇杆
public float maxTorque = 500;//初始化最大力矩
public float maxAngle = 20;//初始化最大旋转角
void Start()
{
GetComponent<Rigidbody>().centerOfMass = new Vector3(0, -0.8f, 0);//赛车刚体重心
}
void FixedUpdate()
{
FLCollider.motorTorque = maxTorque * myJoystick.JoystickTouch.y;//控制力矩
FLCollider.steerAngle = maxAngle * myJoystick.JoystickTouch.x;//控制旋转角
FRCollider.motorTorque = maxTorque * myJoystick.JoystickTouch.y;//控制力矩
FRCollider.steerAngle = maxAngle * myJoystick.JoystickTouch.x;//控制旋转角
}
}
Wheel.cs 该脚本根据车轮碰撞器在行驶过程中和转弯过程中发生的旋转,使车轮游戏对象与车轮碰撞器同步
public class Wheel : MonoBehaviour {
public WheelCollider CPCollider;//声明对应的车轮碰撞器
public float CirValue = 0;//声明车轮滚动角
void Update()
{
transform.rotation = CPCollider.transform.rotation * Quaternion.Euler(CirValue, CPCollider.steerAngle, 0);//旋转车轮
CirValue += CPCollider.rpm * 360 / 60 * Time.deltaTime;//计算车轮滚动角
}
}
SmoothFollow.cs 使摄像机按照一定的距离和高度跟随赛车游戏对象F1同步运动
public class SmoothFollow : MonoBehaviour {
public float distance = 10.0f;//声明跟随距离
public float height = 5.0f;//声明跟随高度
public float heightDamping = 2.0f;//声明高度阻尼
public float rotationDamping = 3.0f;//声明角度阻尼
public float offsetHeight = 1.0f;//声明高度偏移量
Transform selfTransform;
public Transform Target;//声明对象
[AddComponentMenu("Camera-Control/Smooth Follow")]//在功能列表中添加功能选项
void Start()
{
selfTransform = GetComponent<Transform>();
}
void LateUpdate()
{
if (!Target)
return;
float wantedRotationAngle = Target.eulerAngles.y;//预设角度
float wantedHeight = Target.position.y + height;//预设高度
float currentRotationAngle = selfTransform.eulerAngles.y;//当前角度
float currentHeight = selfTransform.position.y;//当前高度
currentRotationAngle = Mathf.LerpAngle(currentRotationAngle, wantedRotationAngle, rotationDamping * Time.deltaTime);//角度渐变至预设角度
currentHeight = Mathf.Lerp(currentHeight, wantedHeight, heightDamping * Time.deltaTime);//高度渐变至预设高度
Quaternion currentRotation = Quaternion.Euler(0, currentRotationAngle, 0);
selfTransform.position = Target.position;//位置调整
selfTransform.position -= currentRotation * Vector3.forward * distance;
Vector3 currentPostion = transform.position;
currentPostion.y = currentHeight;
selfTransform.position = currentPostion;
selfTransform.LookAt(Target.position + new Vector3(0, offsetHeight, 0));//设置摄像机正对中心
}
}