unity3d 摄像机跟随角色时被物体遮挡解决方案

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/qq_44238513/article/details/102502348

unity3d 摄像机跟随角色时被物体遮挡解决方案

未被遮挡时

在这里插入图片描述

为了解决这个问题,在这里我们需要用到 Physics.RaycastAll;使用方法详见圣典

首先 ,我们引入命名空间 System.Collections.Generic,然后在声明三个需要用到的变量

using System.Collections.Generic;//引入命名空间

public class MyCamera1 : MonoBehaviour
{
    //观察目标
    public Transform Target;

    //上次碰撞到的物体
    private List<GameObject> lastColliderObject;

    //本次碰撞到的物体
    private List<GameObject> colliderObject;
}

我们需要发射一条射线,这条射线从角色当前位置发射置摄像机的方向

/*射线可以从头部起始*/

        //这里是计算射线的方向,从主角发射方向是射线机方向
        Vector3 aim = Target.position;
        //得到方向
        Vector3 ve = (Target.position - transform.position).normalized;
        float an = transform.eulerAngles.y;
        aim -= an * ve;

        //在场景视图中可以看到这条射线
        //Debug.DrawLine(target.position, aim, Color.red);

        RaycastHit[] hit;
        hit = Physics.RaycastAll(Target.position, aim, 100f);//起始位置、方向、距离

射线发送完毕后,我们获取发送射线时碰撞到的所有物体,并且添加进本次碰撞到的物体(colliderObject)变量中

因为我的地图、护栏碰撞(不可见)、地面碰撞(不可见)是三个模型,也就是说地图本身是没有任何碰撞的

所以当碰撞到的物体名为护栏或地面时,就不修改其透明度,因为他本身就不可见

这里我偷懒了,直接判断物体名称,可自行改为判断物体 tag

当视角旋转的时候,射线有时候会碰撞到角色,所以,我们获取 tag 判断是否碰撞的物体为角色

//将 colliderObject 中所有的值添加进 lastColliderObject
        for (int i = 0; i < colliderObject.Count; i++)
            lastColliderObject.Add(colliderObject[i]);

        colliderObject.Clear();//清空本次碰撞到的所有物体
        for (int i = 0; i < hit.Length; i++)//获取碰撞到的所有物体
        {
            if (hit[i].collider.gameObject.name != "Editable Poly 1"//护栏
                && hit[i].collider.gameObject.name != "Editable Poly"//地面
                && hit[i].collider.gameObject.tag != "Player")//角色
            {
                //Debug.Log(hit[i].collider.gameObject.name);
                colliderObject.Add(hit[i].collider.gameObject);
                SetMaterialsColor(hit[i].collider.gameObject.renderer, 0.4f);//置当前物体材质透明度
            }
        }

当获取到所碰撞到的所有物体后,我们要修改他的材质透明度,有些物体有很多材质,不知道怎么解决的请看我下面这个方法:

/// 置物体所有材质球颜色 <summary>
    /// 置物体所有材质球颜色
    /// </summary>
    /// <param name="_renderer">材质</param>
    /// <param name="Transpa">透明度</param>
    private void SetMaterialsColor(Renderer _renderer, float Transpa)
    {
        //获取当前物体材质球数量
        int materialsNumber = _renderer.sharedMaterials.Length;
        for (int i = 0; i < materialsNumber; i++)
        {
            //获取当前材质球颜色
            Color color = _renderer.materials[i].color;

            //设置透明度  取值范围:0~1;  0 = 完全透明
            color.a = Transpa;

            //置当前材质球颜色
            _renderer.materials[i].SetColor("_Color", color);
        }
    }

如果本次碰撞到的物体存在于上个物体,那么则说明当前物体还处于遮挡角色状态,所以我们赋值为null

//上次与本次对比,本次还存在的物体则赋值为null
        for (int i = 0; i < lastColliderObject.Count; i++)
        {
            for (int ii = 0; ii < colliderObject.Count; ii++)
            {
                if (colliderObject[ii] != null)
                {
                    if (lastColliderObject[i] == colliderObject[ii])
                    {
                        lastColliderObject[i] = null;
                        break;
                    }
                }
            }
        }

还处于遮挡状态的物体已被赋值为null,那么剩下的物体就是没有处于遮挡状态的,所以我们要重置该物体材质为不透明

//当值为null时则可判断当前物体还处于遮挡状态
        //值不为null时则可恢复默认状态(不透明)
        for (int i = 0; i < lastColliderObject.Count; i++)
        {
            if (lastColliderObject[i] != null)
                SetMaterialsColor(lastColliderObject[i].renderer, 1f);//恢复上次物体材质透明度
        }

我们看一下运行结果:
遮挡时

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_44238513/article/details/102502348