アイデア: カメラを使用して人に光線を照射し、最初に遭遇した物体が人であるかどうかを検出します。キャラクターでない場合は障害物と判断し、透明度を 0.2 にして GameObject 配列に追加します。レイが最初のオブジェクトがキャラクターであることを検出したら、GameObject 配列内のすべてのオブジェクトの透明度を 1 に戻し、配列をクリアします。
PS: このスクリプトはカメラに搭載されているため、動きに続くコード セグメントなどは省略しています。
PS-2: この方法を使用してマテリアルの透明度を変更する場合、新しいマテリアルを追加する必要はありません。キャラクターが遮られると、障害物がインスタンス マテリアル インスタンスを生成して、前のマテリアルを置き換えるように見えるためです。したがって、1 つのオブジェクトのマテリアルの透明度を変更すると、このマテリアルを共有する他のオブジェクトが透明になるという問題はありません。
PS-3: マテリアルのレンダリング モード (Renderer Mode) がOpaqueの場合、 A 値を変更しても透明度が変わらない問題があるため、レンダリング モード (Renderer Mode) をTransparent (透明) に変更できます [これはアルベド マップの可能性があります 質問、A チャンネルがありませんか? ]
PS-4:オクルーダーにはコライダー コンポーネントが必要です。私が遭遇した問題は、障害物にグリッド コライダー コンポーネントがある場合は透明になる可能性があり、グリッド コライダー (または他のコライダー) がない場合は透明度を変更できないことです。
PS-5: 最近、シェーダーで実装された方法を見ました.コードで調整するよりも、どちらがパフォーマンスに大きな影響を与えるかわかりません.
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();//清除数组
}
}