项目场景:

提示:该脚本是挂载到相机上的,当相机视野看不到目标的时候,会自动切换不同视野来捕捉目标,直到看见目标物体为止


问题描述

用途:比如当我们相机跟随主角移动的时候,主角走到了一些角落挡住了相机视线,相机就会自动切换其他方位去捕捉主角

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("Player").transform;
        //获取摄像机与角色的相对位置
        relCameraPos = transform.position - player.position; // 相对位置 = 摄像机位置 - 角色位置
        relCameraPosMag = relCameraPos.magnitude - 0.5f; // 相对位置向量的长度 = 相对位置的长度 - 0.5f  防止光线投射碰撞地面
    }
    void FixedUpdate()
    {
        // 摄像机初始位置 = 角色位置 + 角色与摄像机的相对位置
        Vector3 standardPos = player.position + relCameraPos;
        // 俯视位置 = 角色位置 + 角色正上方 * 相对位置向量的长度
        Vector3 abovePos = player.position + Vector3.up * relCameraPosMag;
        // 创建长度为5的数组 储存5个摄像机位置
        Vector3[] checkPoints = new Vector3[7];
        // 第一个检测 摄像机标准位置
        checkPoints[0] = standardPos;
        // 这三个检测位置为 标准位置到俯视位置之间的三个位置 插值分别为25% 50% 75%
        checkPoints[1] = Vector3.Lerp(standardPos, abovePos, 0.14f);
        checkPoints[2] = Vector3.Lerp(standardPos, abovePos, 0.28f);
        checkPoints[3] = Vector3.Lerp(standardPos, abovePos, 0.42f);
        checkPoints[4] = Vector3.Lerp(standardPos, abovePos, 0.56f);
        checkPoints[5] = Vector3.Lerp(standardPos, abovePos, 0.70f);
        // 最后检测位置为 摄像机俯视位置
        checkPoints[6] = 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)
                // 当前检测位置不合适 返回false
                return false;
        //如果光线投射没有碰撞到任何东西 或者碰撞点为角色位置时 更新当前检测位置为摄像机的新位置
        newPos = checkPos;
        return true;
    }
    void SmoothLookAt()
    {
        // 创建从摄像机到角色的向量
        Vector3 relPlayerPosition = player.position - transform.position;
        // 根据摄像机到角色的向量 创建旋转角度
        Quaternion lookAtRotation = Quaternion.LookRotation(relPlayerPosition, Vector3.up);
        // 让摄像机从 当前角度 平划转至创建的旋转角度
        transform.rotation = Quaternion.Lerp(transform.rotation, lookAtRotation, smooth * Time.deltaTime);
    }
}

效果图

unity worldspace ui 看向摄像机 unity摄像机视野_unity