unity3d教程:镜头跟随及控制(RPG游戏黑暗之光)

发表于2017-03-11
评论0 2.6k浏览
项目开发中镜头跟随及控制是如何实现的?下面以RPG游戏黑暗之光中的镜头跟随及控制为例,给大家介绍下镜头跟随及控制的实现方法,一起来看看吧。

一、镜头的跟随
思路很简单,首先取得镜头初始与角色的距离向量值,然后让相机与角色持续保持该向量距离即可。脚本如下:
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")来记录该值。


对上述脚本进行更新为:
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()方法使镜头围绕角色旋转即可。脚本如下:
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); //会影响positio和rotation  
    float x = tranform.eulerAugles.x; //读取Rotation的x值  
    if(x < 20 || x > 70)  
   {  
        transform.position = originalPosition;  
        transform.rotation = originalRotation;  
    }  
    offsetPosition = transform.position - player.position;  
}  
这样就可以了。

如社区发表内容存在侵权行为,您可以点击这里查看侵权投诉指引