制作地形
2019版
2018版
赛车
车轮
尾灯
代码:CarController
public class CarController : MonoBehaviour {
//拿到车轮碰撞器。
public WheelCollider[] WheelCollider;
//拿到车轮。写完这两个程序,需要到unity里关联一下。
public Transform[] WheelTrans;
//是否在刹车,保存刹车状态
private bool isBreak;
//声音播放器
AudioSource player;
//拿到后面的灯。写完这个程序,需要到unity里关联一下。
public GameObject[] BackLight;
// Use this for initialization
void Start () {
//在这里获取声音播放器
player = GetComponent<AudioSource>();
//调整车辆重心(只能调一次。就是调刚体的重心)
GetComponent<Rigidbody>().centerOfMass = new Vector3(0, 0, 0);
}
// Update is called once per frame
void Update () {
//得到轴:垂直轴、水平轴
float vertical = Input.GetAxis("Vertical");
float horizontal = Input.GetAxis("Horizontal");
/*前进。此处是后轮驱动,所以要拿到后轮。
motorTorque扭矩,它的数值越大,转的越快。此时转的是碰撞器。*/
WheelCollider[2].motorTorque = vertical * 300;
WheelCollider[3].motorTorque = vertical * 300;
//转向。是对前轮做操作。steerAngle旋转。此处最大为50度
WheelCollider[0].steerAngle = horizontal * 50;
WheelCollider[1].steerAngle = horizontal * 50;
//遍历四个轮胎,让轮胎同步车轮碰撞器
for (int i = 0; i < WheelCollider.Length; i++)
{
//获取车轮碰撞器的位置和旋转
Vector3 pos;
Quaternion rotation;
WheelCollider[i].GetWorldPose(out pos, out rotation);
/*GetWorldpose在当前世界座标里的姿态,其实就是获得它的两个参数:位置和旋转。
都用out自动调整两个参数的值,此时获得了碰撞器的数值,下面赋值给轮胎。*/
WheelTrans[i].position = pos;
WheelTrans[i].rotation = rotation;
}
//转速表(关系到声音)。拿任意一个驱动轮即可
Debug.Log(WheelCollider[2].rpm);
//刹车
if(Input.GetKeyDown(KeyCode.Space))
{
isBreak = true;
//刹车的力(要大于上面所给的驱动力)。此处前轮刹车+后轮刹车
WheelCollider[0].brakeTorque = 1000;
WheelCollider[1].brakeTorque = 1000;
WheelCollider[2].brakeTorque = 500;
WheelCollider[3].brakeTorque = 500;
//亮后灯
BackLight[0].SetActive(true);
BackLight[1].SetActive(true);
}
if(Input.GetKeyUp(KeyCode.Space))
{
isBreak = false;
//不是刹车状态时,这个刹车的力为0。
WheelCollider[0].brakeTorque = 0;
WheelCollider[1].brakeTorque = 0;
WheelCollider[2].brakeTorque = 0;
WheelCollider[3].brakeTorque = 0;
//关掉后灯
BackLight[0].SetActive(false);
BackLight[1].SetActive(false);
}
/*播放声音。Mathf.Clamp01限制在0-1。
拿到一个轮胎的转速WheelCollider[2].rpm,假设它3000是最大值。*/
//当转速为最大值时,声音值为1(正常)。
player.pitch = Mathf.Clamp01(WheelCollider[2].rpm / 3000);
//当按了后退键,亮后灯
if(vertical < 0)
{
//亮后灯
BackLight[0].SetActive(true);
BackLight[1].SetActive(true);
}
else if(vertical > 0 && isBreak == false)
{
//关掉后灯
BackLight[0].SetActive(false);
BackLight[1].SetActive(false);
}
}
}
摄像机跟随
系统给了很多跟随脚本。此处的跟随方法,只适合看着玩家背部前进的。
法一相对一法二来说,视野里的汽车更为丰富。因为,法二的相机是不旋转的,看到的汽车部位是不变的;而法一是平滑跟随,摄像机的前方和汽车的前方是逐渐一致的,所以当汽车进行转弯的时候,可以看到汽车的侧身。
法一:平滑跟随
public class FlowTarget : MonoBehaviour {
//跟随的目标
public Transform target;
//跟随的高度
public float height;
//跟随的距离
public float distance;
void Start () {
}
//两个更新的方法:Update和LateUpdate。 把Update改为LateUpdate
//物体移动是在Update里面做的,摄像机是跟随物体移动,所以在LateUpdate里面。
void LateUpdate () {
//法一:平滑跟随。我的前方和目标的前方逐渐一致,利用插值。
//注意这种跟随是不需要对Y轴进行差值的,所以要把摄像机的Y轴清空置为0。
Vector3 forward = transform.forward;
forward.y = 0;
//我的前方和目标的前方是逐渐一致,所以用到差值。1 也可以写成一个变量,在unity中进行调节。* Time.deltaTime为了使各设备一致
//Vector3 newForward = Vector3.Lerp(transform.forward, target.forward, 1 * Time.deltaTime); 此时,摄像机拍摄车顶。需要设定Y轴。
Vector3 newForward = Vector3.Lerp(forward, target.forward, 1 * Time.deltaTime);
//摄像机的位置。1>将原本的target.forward * distance修改为newForward * distance
transform.position = target.position - newForward * distance + Vector3.up * height;
//只写上面那句,没有这句的话,相机不会发生旋转,会有车辆驶出屏幕的情况。
transform.LookAt(target);
}
}
法二:普通跟随
public class FlowTarget : MonoBehaviour {
void LateUpdate () {
//法一:平滑跟随。我的前方和目标的前方逐渐一致,利用插值。
//法二:跟随。
//摄像机的位置。target.forward * distance是个正数,那么减掉它,确保摄像机在物体的后方。
//*distance、*height就是和之前*2都一样,只不过这里不知道具体乘以多少,需要到unity里调节得到。
transform.position = target.position - target.forward * distance + Vector3.up * height;
//只写上面那句,没有这句的话,相机不会发生旋转,会有车辆驶出屏幕的情况。
transform.LookAt(target);
}
}