前期工程实现了角色移动,现需要完成镜头的跟随及控制。
一、镜头的跟随
思路很简单,首先取得镜头初始与角色的距离向量值,然后让相机与角色持续保持该向量距离即可。脚本如下:
NameSpace FollowPlayer
private Transform player;
private Vector3 offsetPosition;
void Start( )
{
player = GameOject.FindGameObjectWithTag("player").transform;
offsetPosition = transform.position - player.position;
}
Void Update( )
{
transform.position = player.position + offsetPosition;
}
以上便实现了镜头跟随角色移动的效果。
二、镜头的控制
镜头的控制分解为镜头拉伸和旋转。
2.1 镜头的拉伸
镜头的拉伸本质就是变更镜头于角色间的向量差,在上述脚本生效后,镜头于角色的向量差就是offsetPosition,而且是一个定值,那么现在就是需要把这个定值根据操作进行变化而已。
使用Input.GetAxis("Mouse ScrollWheel")来记录该值。
对上述脚本进行更新为:
NameSpace FollowPlayer
public float scrollspeed = 5;
void SrollView( )
{
float distance = offsetPosition.magnitude; //却得offsetPosition的向量方差
distance += Input.GetAxis("Mouse ScrollWheel"); //根据鼠标中键变更向量方差值
distance = Math.Clamp(distance,2.5f,17); //限制distance在2.5-17之间,不至于显示视野失常
offsetPosition = offsetPosition.normalized * distance; //先将向量变为标准向量,再乘以方差,变成目标距离向量
}
在void Upadate( )中调用就可以了。
2.2 镜头的左右旋转
思路:读取鼠标在屏幕上X向滑动数值,然后使用tranform.RotateAround()方法使镜头围绕角色旋转即可。脚本如下:
Namespace FollowPlayer
public isRotating = false; //声明标识位
public float rotatespeed = 20;
void RotateView()
{
if( Input.GetMouseDown(1))
{
isRotating = true;
}
else
{
isRotating = false;
}
if( isRotating )
{
tranform.RotateAround(player.position,Vector3.up,Input.GetAixs("Mouse X")*rotatespeed*Time.deltatime);
offsetPosition = transform.position - player.position;
// 注意:此处的重置offsetPosition非常重要,如果不重置offsetPosition,那么当角色固定时,旋转镜头,镜头受限于前期定义的offsetPosition固定,position是不能变得,这样的话镜头只是角度转了,那么显示的状态势必导致主角不在镜头*。
//此处可以理解为卫星沿地球运动,不止角度要变,而且位置要变化,但是其需要保持跟地球的相对距离不变,因此,需要刷新卫星于地球向量差;
//扩展:向量差变化了,并不代表其距离就变化了,现在是要保证其距离不变的情况下,变动其向量差。
}
}
2.3 镜头的上下旋转
类似的,我们在上述的if(isRotating)块中加入上下旋转的控制语句就可以了,脚本如下:
if(isRotating)
{
transform.RotateAround(palyer.position,player.up,Input.GetAixs("Mouse X")*rotatespeed*Time.deltaTime);
transform.RotateAround(player.position,transform.right,Input.GetAixs("Mouse Y")*rotatespeed*Time.deltaTime);
offsetPosition = transform.position - player.position;
//关于transform.rigth,上下调整镜头其实就是沿某轴去调整相机角度而已。将视图放到2D来看,明显是调整X轴(forward对应Z轴,up对应Y轴,right对应X轴)
//那么是player的X轴呢,还是镜头的X轴?还是以卫星与地球的模型来想象,初始状态,镜头与角色的X轴是一致的,因此无论如何旋转都可以;
//但是当镜头左右旋转后呢?它与物体的X轴就不在一线了,如果要求它沿角色的X轴来旋转的话,肯定会连同Z轴一并旋转,这样角色在屏幕就偏斜了
//反而是镜头沿自身X轴旋转,它在屏幕的投影角度是不变的,因此毫无疑问,应该沿镜头的X轴旋转
}
但是这样的话,上下旋转的角度没有限制,是不对的,正如上文提到,上下旋转本质是镜头沿其X轴进行旋转,使X轴规范在一个范围内,注意此处并不能使用Math.Clamp,因为上文说过,镜头的不仅旋转而且还移动了,当旋转受限制了,那么移动还使可以正常移动的,所以需要换一种思路:
首先记录角色位置及角度信息,如果角度X轴超出范围了,那么返回记录的位置。脚本如下:
if(isRotating)
{
Vector3 originalPosition = transform.position;
Quaternion originalRotation = transform.rotation;
transform.RotateAround(palyer.position,player.up,Input.GetAixs("Mouse X")*rotatespeed*Time.deltaTime);
transform.RotateAround(player.position,transform.right,Input.GetAixs("Mouse Y")*rotatespeed*Time.deltaTime);
float x = tranform.eulerAugles.x; //读取Rotation的x值
if(x < 20 || x > 70)
{
transform.position = originalPosition;
transform.rotation = originalRotation;
}
offsetPosition = transform.position - player.position;
}
这样就可以了。今日的总结到此为止。