学习Unity过程中,遇到了角色被墙体遮挡这一问题。能想到的解决方法有“对墙体不进行渲染”和“拉近视角”这两种,前者好像在网游里见得比较多,而其他端游和主机游戏还是用的后者。

unity3d 物体遮挡轮廓 unity3d 建筑挡住镜头_unity3d 物体遮挡轮廓

这里试着用拉近视角的方式,令角色物体头部每帧朝相机位置发出射线,若射线打到了墙体,则将相机移动到打击点处。
代码如下:

public float distance;
    public Transform character;
    void Start()
    {
        character = GameObject.Find("Player").transform;    //传入角色物体的引用
        distance = Vector3.Distance(transform.position, character.position);  //记录相机和角色的初始距离
    }
    void MoveCamera()
    {
        if (Physics.Raycast(character.position, //从角色物体的原点发出射线(一般情况下原点是角色模型的脚部,所以需要自己根据实际调整该点)
                            transform.position - character.position,    //射线方向
                            out RaycastHit hit,
                            distance)    //最大距离只需要到相机为止
            && hit.collider.CompareTag("Wall"))     //如果射线打到了collider,则判断其是否是墙体
        {
            Vector3 newPoint = hit.point;   //若是墙体,则将打到的点设为相机的新位置
            transform.position = newPoint;
        }
        else
        {
            //如果射线没有打到任何collider,或者打到的不是墙体,则将相机和角色之间的距离还原
            Vector3 p = (transform.position - character.position).normalized * distance;
            transform.position = character.position + p;
        }
    }

让我来运行看看——

unity3d 物体遮挡轮廓 unity3d 建筑挡住镜头_游戏_02


这正是我想要的效果。再优化一下,使用Vector3.Lerp()方法使相机移动更为平滑,修改代码如下:

float distance;
    Transform character;
    void Start()
    {
        character = GameObject.Find("Player").transform;    //传入角色物体的引用
        distance = Vector3.Distance(transform.position, character.position);  //记录相机和角色的初始距离
    }
    void MoveCamera()
    {
        if (Physics.Raycast(character.position, //从角色物体的原点发出射线(一般情况下原点是角色模型的脚部,所以需要自己根据实际调整该点)
                            transform.position - character.position,    //射线方向
                            out RaycastHit hit,
                            distance)    //最大距离只需要到相机为止
            && hit.collider.CompareTag("Wall"))     //如果射线打到了collider,则判断其是否是墙体
        {
            Vector3 newPoint = hit.point;   //若是墙体,则将打到的点设为相机的新位置
            transform.position = Vector3.Lerp(transform.position, newPoint, 0.5f);  //速度比例这里设为0.5,如果感觉移动慢了可以调高数值
        }
        else
        {
            //如果射线没有打到任何collider,或者打到的不是墙体,则将相机和角色之间的距离还原
            Vector3 p = (transform.position - character.position).normalized * distance;
            Vector3 newPoint = character.position + p;
            transform.position = Vector3.Lerp(transform.position, newPoint, 0.5f);
        }
    }

问题这样就解决了。