unity 中间摄像机的移动

现在很多情况下都会出现游戏摄像机跟随着人物移动,网上关于这个也是很多的,但是有时候只是和游戏人物简单的出现保持相对的距离,这样子运动起来会很干涩,动作不够连贯,给游戏玩家很不好的感觉。


如果遇到墙,和其他的物体对游戏主角进行遮挡,这个样子,就无法看到游戏玩家了。下面的方法巧妙的解决了这个问题。

unity3d 角色队形跟随 unity视角跟着人物走_unity3d 角色队形跟随

代码实现 


首先定义几个变量:


public float smooth = 1.5f;
    private Transform player;
    private Vector3 relCameraPos; //相对位置摄像机对人物
    private float relCameraPosMag; //摄像机和人物的距离
    private Vector3 newPos;  //摄像机试着抵达的位置





对几个变量进行初始化:


void Awake()
    {
        player = GameObject.FindGameObjectWithTag(Tags.player).transform;
        //摄像机相对位置 = 摄像机位置 - 玩家位置
        relCameraPos = transform.position - player.position;
        //实际向量长度-0.5 小一点
        relCameraPosMag = relCameraPos.magnitude - 0.5f;

}







下面在fixedUpdate()里面是重点。




定义五个摄像机位置:Vector3[] checkPoints = new Vector3[5];




再把第一个位置设为摄像机初始的位置,把最后一个位置设为于游戏人物垂直上方的位置。


//摄像机的初始位置 = 玩家位置 + 相对位置
Vector3 standardPos = player.position + relCameraPos;
//摄像机的俯视位置 = 玩家位置 + 玩家正上方 * 相对位置向量长度
Vector3 abovePos = player.position + Vector3.up * relCameraPosMag;




摄像机如下图一步一步慢慢升上来的。


unity3d 角色队形跟随 unity视角跟着人物走_光线投射_02





摄像头会慢慢位移,直到射线能过看到的地方。




checkPoints[4] = abovePos;

        for (int i = 0;i<checkPoints.Length;i++)
        {
            if (ViewingPosCheck(checkPoints[i]))
            {
                break;
            }
        }







//使用光线投射的方法检测摄像机能否投射碰撞到玩家 
    bool ViewingPosCheck(Vector3 checkPos)
    {

        RaycastHit hit;

        if (Physics.Raycast(checkPos,player.position-checkPos,out hit,relCameraPosMag))
        {
            if (hit.transform!=player)
            {
                return false;
            }
        }

        newPos = checkPos;
        return true;
    }



下面的函数使摄像机在运动的过程中始终面对着游戏人物。


//使摄像机函数在移动过程中始终面对玩家
    void SmoothLookAt()
    {
        Vector3 relPlayPosition = player.position - transform.position;

        Quaternion lookAtRotation = Quaternion.LookRotation(relPlayPosition, Vector3.up);

        transform.rotation = Quaternion.Lerp(transform.rotation, lookAtRotation, smooth * Time.deltaTime);
    }








using UnityEngine;
using System.Collections;

public class CameraMovement : MonoBehaviour {

    public float smooth = 1.5f;
    private Transform player;
    private Vector3 relCameraPos; //相对位置摄像机对人物
    private float relCameraPosMag; //摄像机和人物的距离
    private Vector3 newPos;  //摄像机试着抵达的位置

    void Awake()
    {
        player = GameObject.FindGameObjectWithTag(Tags.player).transform;
        //摄像机相对位置 = 摄像机位置 - 玩家位置
        relCameraPos = transform.position - player.position;
        //实际向量长度-0.5 小一点
        relCameraPosMag = relCameraPos.magnitude - 0.5f;

    }

    void FixedUpdate()
    {

        //摄像机的初始位置 = 玩家位置 + 相对位置
        Vector3 standardPos = player.position + relCameraPos;
        //摄像机的俯视位置 = 玩家位置 + 玩家正上方 * 相对位置向量长度
        Vector3 abovePos = player.position + Vector3.up * relCameraPosMag;

        Vector3[] checkPoints = new Vector3[5];

        checkPoints[0] = standardPos;

        checkPoints[1] = Vector3.Lerp(standardPos, abovePos, 0.25f);
        checkPoints[2] = Vector3.Lerp(standardPos, abovePos, 0.5f);
        checkPoints[3] = Vector3.Lerp(standardPos, abovePos, 0.75f);


        checkPoints[4] = abovePos;

        for (int i = 0;i<checkPoints.Length;i++)
        {
            if (ViewingPosCheck(checkPoints[i]))
            {
                break;
            }
        }

        transform.position = Vector3.Lerp(transform.position, newPos, smooth * Time.deltaTime);

        SmoothLookAt();
    }


    //使用光线投射的方法检测摄像机能否投射碰撞到玩家 
    bool ViewingPosCheck(Vector3 checkPos)
    {

        RaycastHit hit;

        if (Physics.Raycast(checkPos,player.position-checkPos,out hit,relCameraPosMag))
        {
            if (hit.transform!=player)
            {
                return false;
            }
        }

        newPos = checkPos;
        return true;
    }
    //使摄像机函数在移动过程中始终面对玩家
    void SmoothLookAt()
    {
        Vector3 relPlayPosition = player.position - transform.position;

        Quaternion lookAtRotation = Quaternion.LookRotation(relPlayPosition, Vector3.up);

        transform.rotation = Quaternion.Lerp(transform.rotation, lookAtRotation, smooth * Time.deltaTime);
    }
}