Unity实现遮挡人物的障碍物体设为透明,并在不遮挡时恢复的个人解决方法

   思路:通过摄像机向人物发射射线,检测第一个碰到的物体是否为人物。如果不是人物,那么就判断为障碍,将其透明度设为0.2,并将其添加入一个GameObject数组中。当射线检测到第一个物体是人物时,将这个GameObject数组中的所有物体透明度恢复为1,并清空这个数组。

PS:  此脚本挂载于 摄像机上,我省略了跟随移动的代码段 等

PS-2: 用此方法改变材质的透明度,不需要额外新建材质。因为似乎在人物被遮挡时,障碍物会生成一个Instance材质实例更换之前的材质。因此不会出现改变单个物体的材质透明度时,导致其它共用此材质的物体都变透明的问题。

PS-3: 若材质的渲染模式(Renderer Mode)为Opaque时,出现更改A值透明度不发生变化的问题,则可以把渲染模式(Renderer Mode)改为Transparent(透明)[这个可能是Albedo贴图的问题,少了A通道?]

PS-4: 需要遮挡物带有碰撞器组件。我遇到的问题是:当障碍物有网格碰撞器组件时,才能透明;如果不带有网格碰撞器(或者其它碰撞器),那么就无法改变透明度

PS-5:最近又看到了用shader实现的方法,不知道和用代码调整哪个对性能影响更大

    public Transform player;

    RaycastHit HitInfo;
    List<GameObject> TransparentObjects = new List<GameObject>();
 
    void Update()
    {

        SetTrans();

    }

    private void SetTrans()
    {

        Vector3 Direction = player.position - transform.position;//射线方向为摄像头指向人物

        RaycastHit[] hits;
        
        if (Physics.Raycast(transform.position,Direction,out HitInfo))
        {
            if (HitInfo.transform.tag != "Player")//若人物被遮挡了
            {
                hits = Physics.RaycastAll(transform.position, Direction, 100f,1<< LayerMask.NameToLayer("Default"));//只检测Default图层的物体,其它图层检测不到
                for (int i = 0; i < hits.Length; i++)
                {
                    var hit = hits[i];
                    if (hit.transform.tag == "Player")
                    {
                        return;
                    }
                    else
                    {
                        ClearTransparentObjects();
首先先将透明物体全部恢复,不然会出现人物持续被遮挡时,多个物体全部变成透明的问题。
也就是说,只能将挡在人物前面的首个物体透明。如果人物前面有多个物体遮挡,这句语句可以删掉或进行调整

                        if (hit.transform.GetComponent<MeshRenderer>())//若障碍物带有碰撞器组件
                        {
                            if(hit.transform.GetComponent<MeshRenderer>().material.color.a != 0.2f)//若障碍物的透明度不为0.2
                            {
                                var ChangeColor = hit.transform.GetComponent<MeshRenderer>().material.color;
                                ChangeColor.a = 0.2f;

                                SetMaterialRenderingMode(hit.transform.GetComponent<MeshRenderer>().material, RenderingMode.Transparent);

                                hit.transform.GetComponent<MeshRenderer>().material.color = ChangeColor;
                                TransparentObjects.Add(hit.transform.gameObject);//将透明物体添加到数组中


                                Debug.Log("射线检测到的物体名为:" + hit.transform.name);

                            }                       
                        }
                        
                    }

                }
            }
            else//若人物没有被遮挡
            {
                ClearTransparentObjects();
            }
            
        }
        
    }

    void ClearTransparentObjects()//将透明物体恢复不透明
    {
        if (TransparentObjects != null)
        {
            for (int i = 0; i < TransparentObjects.Count; i++)
            {
                var ChangeColor = TransparentObjects[i].transform.GetComponent<MeshRenderer>().material.color;
                ChangeColor.a = 1f;
           
                TransparentObjects[i].transform.GetComponent<MeshRenderer>().material.color = ChangeColor;
            }
            TransparentObjects.Clear();//清除数组
        }
    }

猜你喜欢

转载自blog.csdn.net/qianhang120/article/details/128145939