以前写过的高级摄像机跟随,分享一下,

  • 源码:
public class CameraFollow : MonoBehaviour {

    public GameObject player;        主角



    private Vector3 disV3;        用来储存摄像机与主角之间的距离向量

    private Vector3 StartV3;        用来表示一开始相机的位置

    private Vector3 UpV3;        用来储存相机在主角正上方的位置



    private Vector3[] allV3 = null;    用来储存相机差值移动的5个点



    private Ray mRay;            射线

    private RaycastHit mInfo;        射线的碰撞信息



    private Vector3 endPos;             用来判断相机需要移动到哪个点,存储上方的数组元素



    void Start () {

        一开始计算出相机与主角之间的距离

        disV3 = this.transform.position - player.transform.position;

        为数组实例化,赋予5个内存空间

        allV3 = new Vector3[5];

    }





    --------------------------------------------------------------------------------

    O                    相机5个位置:

    O                      主角: P

    O                  相机: O

    O

    O ---->  一开始的位置





    P

    --------------------------------------------------------------------------------



    摄像机移动通常都写在LateUpdate里面,保证画面是最新的

    void LateUpdate () {

        每一帧都让相机朝向主角

        this.transform.LookAt (player.transform.position);



        相机在第一个点的位置,他等于  相机与主角的距离 + 主角的位置

        如果不加上主角的位置,那么就是相机的位置就是相对于(0,0,0)原点的

        StartV3 = disV3 + player.transform.position;

        相机在主角正上方的位置,他等于向上的方向向量 * 相机与主角的距离

        要加上主角的位置让他相对于主角,不然相机在主角正上方的位置就是相对于(0,0,0)的

        两个三维坐标不可以计算,我们要把 disV3 取模,方法是 disV3.magnitude

        UpV3 = Vector3.up * disV3.magnitude + player.transform.position;



        第一个点

        allV3 [0] = StartV3;

        第二个点,他是第一个点到最后一个点的0.25

        allV3 [1] = Vector3.Lerp (StartV3, UpV3, 0.25f);

        第三个点,他是第一个点到最后一个点的0.50

        allV3 [2] = Vector3.Lerp (StartV3, UpV3, 0.5f);

        第四个点,他是第一个点到最后一个点的0.75

        allV3 [3] = Vector3.Lerp (StartV3, UpV3, 0.75f);

        第五个点

        allV3 [4] = UpV3;



        用一个for循环来遍历相机从第一个点开始到第五个点是否能看到主角

        for (int i = 0; i < allV3.Length; i++) {



            让射线的起始点等于相机从第一个到第五个点的坐标

            用射线判断相机在各个位置是否射得到主角

            mRay.origin = allV3 [i];

            让射线的方向等于从相机射向主角,用主角坐标减去相机的坐标

            原理请看结尾处:

            mRay.direction = player.transform.position - allV3 [i];



            以相机在 i 这个点的坐标向主角发射一条主角与相机的距离长度的射线

            (当然你也可以写1000或者10000)

            if (Physics.Raycast (mRay, out mInfo, disV3.magnitude)) {



                判断他射到的是否是主角

                if (mInfo.collider.gameObject.tag == "Player") {

                    如果是主角,说明相机可以看见主角,让临时变量endPos等于相机的坐标

                    然后break跳出循环,将endPos赋值给相机,让相机差值向endPos坐标移动

                    endPos = allV3 [i];                 |

                    break;                     |

                }                         |

            }                             |

        }                             V

        this.transform.position = Vector3.Lerp (this.transform.position, endPos, 0.01f);

    }

}



如图相机与这个点(向量)等于,原点到主角的向量 + 主角到相机的向量 。可以看出,如果将相机这个点减去主角那个点,会得到一个向量,这个向量的方向是主角指向相机。

所以,我们射线如果要从相机指向主角,应该是用主角的坐标减去相机的坐标



主角 --------> 相机

∧            ? 

|          /

|       /

|    /

原点