通常第一人称或第三人称游戏,相机会跟随角色移动,故而要实现下面3个功能。
- 相机跟随物体移动
- 鼠标控制相机的角度
- 鼠标滚轮调整相机与物体的距离
下面实现的是一套通用的第三人称相机组件。
确定相机与物体的位置关系
在YZ平面和XZ平面,物体(此处以坦克为例)和相机的相对位置如下图,可以看到距离、角度和高度。
跟随算法
新建名为CameraFollow的script脚本,实现相机跟随的功能,代码如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CameraFollow : MonoBehaviour
{
//距离
public float distance = 15;
//横向角度
public float rot = 0;
//纵向角度
private float roll = 30f * Mathf.PI * 2 / 360;
//目标物体
private GameObject target;
// Use this for initialization
void Start () {
//找到坦克
target = GameObject.Find("tank");
}
// Update is called once per frame
void LateUpdate () {
//一般判断
if (target == null)
return;
if (Camera.main == null)
return;
//目标的坐标
Vector3 targetPos = target.transform.position;
//用三角函数计算相机位置
Vector3 cameraPos;
float d = distance * Mathf.Cos(roll);
float height = distance * Mathf.Sin(roll);
cameraPos.x = targetPos.x + d * Mathf.Cos(rot);
cameraPos.z = targetPos.z + d * Mathf.Sin(rot);
cameraPos.y = targetPos.y + height;
Camera.main.transform.position = cameraPos;
//对准目标
Camera.main.transform.LookAt(target.transform);
}
}
最后将该脚本拉到相机身上。并绘制一块地形(方便看出物体的移动)。运行游戏,既可以看见相机跟随在坦克后面。如下图所示:
设置跟随目标
在CameraFollow类中添加SetTarget方法,设置相机对准的目标。不同的三维模型其中心点会有所不同。中心点不同,玩家看到的视角就不同。为制定相机对准的中心点,特制定如下规则:
- 如果对准的物体带有名为cameraPoint的子物体,那么相机对准cameraPoint子物体。
- 如果物体不包含名为cameraPoint的子物体,则对准物体中心点。
下面是相对应的代码:
public void SetTarget(GameObject target)
{
if (target.transform.FindChild("cameraPoint") != null)
this.target = target.transform.FindChild("cameraPoint").gameObject;
else
this.target = target;
}
在炮塔上方添加一个名为cameraPoint的方块(作为tank的子物体),精确控制相机对准的中心点。如下图所示:
横向旋转相机
前面是键盘是“上下左右”控制坦克,然后相机进行跟随。下面我们要实现的目标是通过鼠标来控制相机的旋转。鼠标向左移动时。相机便会“左转”,同理,鼠标右移,相机便“右转”。这样就可以全方位看见坦克模型了。
Mouse X和Mouse Y代表着鼠标的移动增量,也就是说当鼠标向左移动时, Input.GetAxis(“Mouse X”) 的值会增大,向右则减小。只要让旋转角度rot与Mouse X成正比关系,便能够通过鼠标控制相机的角度。
在CameraFollow类中新增变量rotSpeed,表示相机旋转的速度。然后编写Rotate()方法,使相机的横向角度rot随着Input.GetAxis(“Mouse X”)的改变而改变,代码如下所示:
//横向旋转速度
public float rotSpeed = 0.2f;
//横向旋转
void Rotate()
{
float w = Input.GetAxis("Mouse X") * rotSpeed;
rot -= w;
}
最后在LateUpdate()中调用Rotate() 就OK了。代码如下,然后运行游戏就可以从各个角度观察坦克啦。
//横向旋转
Rotate();
纵向旋转相机
玩家不仅可以横向操控相机的角度,还可以纵向调整相机的高度。下面的代码通过maxRoll和minRoll定义了相机的纵向旋转范围(以弧度表示),通过rollSpeed给出旋转的速度。
// 纵向角度范围
private float maxRoll = 70f * Mathf.PI * 2 / 360;
private float minRoll = -10f * Mathf.PI * 2 / 360;
//纵向旋转速度
private float rollSpeed = 0.2f;
在CameraFollow类中编写Roll方法,使相机纵向角度roll随着Input.GetAxis(“Mouse Y”)的改变而改变。最后在LateUpdate()里面调用它,代码如下所示:
//纵向旋转
void Roll()
{
float w = Input.GetAxis("Mouse Y") * rollSpeed * 0.5f;
roll -= w;
if (roll > maxRoll)
roll = maxRoll;
if (roll < minRoll)
roll = minRoll;
}
滚轮调节距离
本节将会实现用鼠标滚轮调节相机与坦克之间距离的功能。输入轴Mouse ScrollWhell代表鼠标滚轮,即通过Input.GetAxis(“Mouse ScrollWheel”)可以获取鼠标滚轮的增量,当滚轮向上滚动时该值减少,向下滚动时该值增加。添加maxDistance、minDistance和zoomSpeed这3个调整距离的变量其中maxDistance和minDistance表示距离的范围,zoomSpeed表示缩放的速度,代码如下所示:
//距离范围
public float maxDistance = 22f;
public float minDistance = 5f;
//距离变化速度
public float zoomSpeed = 0.2f;
在CameraFollow类中添加Zoom方法实现距离缩放,并在LateUpdate()里面调用它,代码如下所示:
void Zoom()
{
if(Input.GetAxis("Mouse ScrollWheel") > 0)
{
if (distance > minDistance)
distance -= zoomSpeed;
}
else if (Input.GetAxis("Mouse ScrollWheel") < 0)
{
if (distance < maxDistance)
distance += zoomSpeed;
}
}
运行游戏,滚动鼠标滚轮,相机与坦克的距离就会随之改变。