上文提到,解决相机不能直接看到物体我选择的解决方法是在相机和物体中连一条射线,射线上碰到的物体通过改变透明度来达到直视物体的效果,但是这里面有个问题:

当物体遇到上图的问题的时候,会涉及到多个物体的透视,这个时候必然是把三个障碍物全部改透明度。假设一个场景,我们从下往上看调整镜头,那么第一个透明的应该是黑色障碍物,然后是蓝色和绿色。然后继续上抬,这时,黑色就退出了射线,透明度还原,直到几乎垂直,绿色还原。观察到这一现象,我第一反应是用队列来处理,FIFO。另外,当时我注意到貌似对射线第一个碰到的物体进行入队就行,直到射线第一个碰到的不再是这个物体,就可以认为物体出队。

Queue<GameObject> RaycastHitList = new Queue<GameObject>();
RayCast(transform.position, player.position, (transform.position - player.position).magnitude, out hit);
if(RaycastHitList.Peek()!=GameObject.Find(hit.collider.name))
{
  if(hit.collider.name == "Wall")
  {
    Object = GameObject.Find(hit.collider.name);
    RaycastHitList.Add(Object);
    Object.GetComponent<Renderer>().material.color = new Color(Object.GetComponent<Renderer>().material.color.r, Object.GetComponent<Renderer>().material.color.g, Object.GetComponent<Renderer>().material.color.b, 0.4f);
  }
  Object = RaycastHitList.Pop();
  Object.GetComponent<Renderer>().material.color = new Color(Object.GetComponent<Renderer>().material.color.r, Object.GetComponent<Renderer>().material.color.g, Object.GetComponent<Renderer>().material.color.b, 1.0f);
}

然而实际上在使用过程中发现这种方法有缺陷,因为不是所有物体的遮罩都符合FIFO模型,所以需要实时判定哪些物体在射线上,RayCastAll函数就可以满足这个判定条件。RayCastAll函数的返回值是一个RayCast类型的数组,可以通过这个数组货渠道射线上的所有物体的信息。

我们需要四个数组,一个用于存储原本的数组A信息,一个用于存储新获取的数组B信息,一个用于存储B于A的差集,一个用于存储A于B的差集。

解释一下,B于A的差集表示A有,B没有的元素,即从射线之间退出的元素。A于B表示B有,A没有的元素,即增加到射线之间的元素。

RaycastHit[] Hit;
        Hit = Physics.RaycastAll(transform.position, CirclePoint.position - transform.position, (transform.position - CirclePoint.position).magnitude);
        foreach (RaycastHit Hitelement in Hit)
        {
            GameObject Object;
            Object = GameObject.Find(Hitelement.collider.name);
            Data_New.Add(Object);
        }
        Data_NewExceptCurrent = Data_New.Except(Data_Current).ToList();
        foreach (GameObject Object in Data_NewExceptCurrent)
        {
            Object.GetComponent<Renderer>().material.color = new Color(Object.GetComponent<Renderer>().material.color.r, Object.GetComponent<Renderer>().material.color.g, Object.GetComponent<Renderer>().material.color.b, 0.4f);
        }
        Data_CurrentExceptNew = Data_Current.Except(Data_New).ToList();
        foreach (GameObject Object in Data_CurrentExceptNew)
        {
            Object.GetComponent<Renderer>().material.color = new Color(Object.GetComponent<Renderer>().material.color.r, Object.GetComponent<Renderer>().material.color.g, Object.GetComponent<Renderer>().material.color.b, 1.0f);
        }
        Data_Current.Clear();
        foreach (GameObject Object in Data_New)
        {
            Data_Current.Add(Object);
        }
        Data_New.Clear();

每次update会对视线碰到的物体进行一次处理,虽然这样效率有点低,不过暂时想不到更好的优化方式,目前唯一的优化方式就只有update时之判断原数据又没有发生变化,如果有才进行更新这种。

以上就是目前我关于视线受阻时候怎么处理的方法,以后如果有更好的方法再更新好了。