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();//清除数组
}
}
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
THE END
二维码