2评论

Unity遮挡透明渐变

清风 2018-08-13 593浏览

想免费获取内部独家PPT资料库?观看行业大牛直播?点击加入腾讯游戏学院游戏开发行业精英群711501594

开发游戏过程中,出现角色被场景中的建筑物遮挡的情况该怎么办?下面就给大家介绍下遮挡后使用透明渐变的处理方法。

遮挡透明若没有渐变实现方法:
  • 透明中物体存在list中
  • 每过一段时间(可以每帧,但是流畅性会降低)摄像机发送一条射线向玩家,out hitInfo
  • list与hitInfo比对,将在list中但是没有在hitInfo中的物体转变成不透明,list.remove;将在hitInfo中但是没有在list中转变成透明,list.add

若有渐变,实现比较麻烦一点,物体有两个状态:转变成透明过程中、转变成不透明过程中,添加两个list(InTransparent,outTransparent)对应两种状态,那么维护两个list即可:

1、未遮挡->遮挡,查看outTransparent,如果有该物体,从outTransparent移入InTransparent,outTransparent  remove;如果没有添加新的加入InTransparent

2、遮挡->未遮挡,查看InTransparent,如果有该物体,从InTransparent移入outTransparent,InTransparent remove;如果没有添加新的加入outTransparent

摄像机CameraFollow.cs:
public class CameraFollow : MonoBehaviour
{
    public static CameraFollow instance;
    public Transform Player;
    public List<CameraMaskInfo> Mask;
    public List<CameraMaskInfo> InTransparentList;
    public List<CameraMaskInfo> OutTransparentList;
    RaycastHit[] hitInfo;
    void Awake()
    {
        instance = this;
    }
    void Start()
    {
        StartCoroutine(IEMask());
    }
    public void ClearMask()
    {
        Mask.Clear();
        InTransparentList.Clear();
        OutTransparentList.Clear();
    }
    IEnumerator IEMask()
    {
        while (true)
        {
            hitInfo = Physics.CapsuleCastAll(FollowTarget.position + Vector3.up * 0.2f, FollowTarget.position - Vector3.up * 0.1f, 0.2f, (transform.position - FollowTarget.position).normalized, 100f, layerMask);
            bool flag;
            for (int i = Mask.Count - 1; i >= 0; i--)
            {
                flag = false;
                for (int j = 0; j < hitInfo.Length; j++)
                {
                    if (Mask[i].GetObj() == hitInfo[j].collider.gameObject)
                    {
                        flag = true;
                        break;
                    }
                }
                if (!flag)
                {
                    Mask[i].PutOutTransparent();
                    Mask.RemoveAt(i);
                }
            }
            for (int i = 0; i < hitInfo.Length; i++)
            {
                flag = false;
                for (int j = 0; j < Mask.Count; j++)
                {
                    if (hitInfo[i].collider.gameObject == Mask[j].GetObj())
                    {
                        flag = true;
                        break;
                    }
                }
                if (!flag)
                {
                    CameraMaskInfo maskInfo = new CameraMaskInfo(hitInfo[i].collider.gameObject);
                    maskInfo.PutInTransparent();
                    Mask.Add(maskInfo);
                }
            }
        }
        yield return new WaitForSeconds(0.2f);
    }
    void Update()
    {
        for (int i = InTransparentList.Count - 1; i >= 0; i--)
        {
            InTransparentList[i].Sub();
        }
        for (int i = OutTransparentList.Count - 1; i >= 0; i--)
        {
            OutTransparentList[i].Add();
        }
    }
}

遮挡物体CameraMaskInfo.cs:
using UnityEngine;
using System.Collections;
public class CameraMaskInfo 
{
    private GameObject obj;
    private Shader[] preMaterialShader;
    public bool isDestroy;
    #region get
    public GameObject GetObj()
    {
        return obj;
    }
    public Shader[] GetpreMaterialShader()
    {
        return preMaterialShader;
    }
    #endregion
    public CameraMaskInfo(GameObject obj)
    {
        this.obj = obj;
    }
    public void PutInTransparent()
    {
        int id = -1; 
        for (int i = 0; i < CameraFollow.instance.OutTransparentList.Count; i++)
        {
            if (CameraFollow.instance.OutTransparentList[i].GetObj() == obj)
            {
                id = i;
                //如果在out里面有,那么说明该物体的shader已经被改变,只能从之前的获得
                preMaterialShader = CameraFollow.instance.OutTransparentList[i].GetpreMaterialShader();
                CameraFollow.instance.InTransparentList.Add(CameraFollow.instance.OutTransparentList[i]);
                CameraFollow.instance.OutTransparentList.RemoveAt(i);
                break;
            }
        }
        if (id==-1)
        {
            preMaterialShader = new Shader[obj.renderer.materials.Length];
            for (int i = 0; i < obj.renderer.materials.Length; i++)
            {
                preMaterialShader[i] = obj.renderer.materials[i].shader;
                obj.renderer.materials[i].shader = Shader.Find("Transparent/Diffuse");
            }
            CameraFollow.instance.InTransparentList.Add(this);
        }
    }
    public void PutOutTransparent()
    {
        int id = -1;
        for (int i = 0; i < CameraFollow.instance.InTransparentList.Count; i++)
        {
            if (CameraFollow.instance.InTransparentList[i].GetObj() == obj)
            {
                id = i;
                CameraFollow.instance.OutTransparentList.Add(CameraFollow.instance.InTransparentList[i]);
                CameraFollow.instance.InTransparentList.RemoveAt(i);
                break;
            }
        }
        if (id == -1)
        {
            CameraFollow.instance.OutTransparentList.Add(this);
        }
    }
    public void Add()
    {
        for (int i = 0; i < obj.renderer.materials.Length; i++)
        {
            obj.renderer.materials[i].color = new Color(obj.renderer.materials[i].color.r, obj.renderer.materials[i].color.g, obj.renderer.materials[i].color.b, obj.renderer.materials[i].color.a + Time.deltaTime * 2f);
        }
        if (obj.renderer.materials[0].color.a >= 0.95f)
        {
            for (int i = 0; i < obj.renderer.materials.Length; i++)
            {
                obj.renderer.materials[i].color = new Color(obj.renderer.materials[i].color.r, obj.renderer.materials[i].color.g, obj.renderer.materials[i].color.b, 1f);
            }
            SetPreShader();
            CameraFollow.instance.OutTransparentList.Remove(this);
        }
    }
    public void Sub()
    {
        for (int i = 0; i < obj.renderer.materials.Length; i++)
        {
            obj.renderer.materials[i].color = new Color(obj.renderer.materials[i].color.r, obj.renderer.materials[i].color.g, obj.renderer.materials[i].color.b, obj.renderer.materials[i].color.a - Time.deltaTime * 2f);
        }
        if (obj.renderer.materials[0].color.a <= 0.3f)
        {
            CameraFollow.instance.InTransparentList.Remove(this);
        }
    }
    private void SetPreShader()
    {
        for (int i = 0; i < obj.renderer.materials.Length; i++)
        {
            obj.renderer.materials[i].shader = preMaterialShader[i];
        }
    }
}

效果: