Unity 相机被遮挡的判断与处理

原理

首先,将相机与角色之间的距离分为多个等级,每次手动调整相机距离后,就记录偏好的距离等级。从相机处向人发射一条射线,如果检测到相机与人之间有物体,就把相机自动往前移动一级,直到相机不再被遮挡为止。随后计算偏好距离等级的相机位置是否被遮挡,如果没有被遮挡了,就恢复到原来的相机距离。

效果

代码

    /*
        相机距离分级调整
        取初始距离为单位长度,随后每次调整都以此为单位
        用单位向量乘以单位长度即可得到位移矢量
    */

    //单位长度
    float unit;

    void ScrollToAdjustView()
    {
        if (Input.GetAxis("Mouse ScrollWheel") > 0)
        {
            ViewPlus();
            preferdLevel = currentLevel;
        }
        else if (Input.GetAxis("Mouse ScrollWheel") < 0)
        {
            ViewMinus();
            preferdLevel = currentLevel;
        }
    }

    void ViewPlus()
    {
        if (RelativePosition.magnitude <= MinViewDistance) return;
        transform.Translate(-RelativePosition.normalized * unit, Space.World);
        RelativePosition = transform.position - focus.position;
        currentLevel--;
    }

    void ViewMinus()
    {
        if (RelativePosition.magnitude >= MaxViewDistance) return;
        transform.Translate(RelativePosition.normalized * unit, Space.World);
        RelativePosition = transform.position - focus.position;
        currentLevel++;
    }

    /*-----------------视野遮挡处理------------------*/

    /*
        如果视野被遮挡,就逐级拉近相机的距离
        如果原机位不再被遮挡,则恢复原机位
    */

    //当前视角级别
    int currentLevel = 1;
    //偏好视野级别
    int preferdLevel = 1;

    //是否需要恢复原机位
    bool resumable = false;

    void OcclusionJudge()
    {
        if (Physics.Raycast(transform.position, -RelativePosition.normalized, RelativePosition.magnitude - unit))               //如果机位被遮挡
        {
            resumable = true;
            while (Physics.Raycast(transform.position, -RelativePosition.normalized, RelativePosition.magnitude - unit))
            {
                ViewPlus();
            }
        }

        if (!resumable) return;             //如果不需要恢复

        Vector3 PositionToResume = focus.position + RelativePosition.normalized * unit * preferdLevel;              //计算偏好距离所在位置

        if (resumable && !Physics.Raycast(PositionToResume, -RelativePosition.normalized, (preferdLevel - 1) * unit))       //原机位没被遮挡,恢复原位
        {
            while (currentLevel != preferdLevel)
            {
                ViewMinus();
            }
            resumable = false;
        }
    }

猜你喜欢

转载自blog.csdn.net/weixin_43673589/article/details/123299970