Unity3d - RPG项目学习笔记(五)

时间:2022-09-19 21:36:33

前期工程实现了角色移动,现需要完成镜头的跟随及控制。

一、镜头的跟随

思路很简单,首先取得镜头初始与角色的距离向量值,然后让相机与角色持续保持该向量距离即可。脚本如下:

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;

}

这样就可以了。今日的总结到此为止。