参考了这两位的文章:
最终效果:树没有挡住主角前、树挡住主角后变透明
下面是我的解决方案:
需要注意的设置:需要变透明的物体一定要有碰撞盒(可以被射线检测到)unity射线检测检测不到物体3D道具,shader的渲染模式一定是Transparent(即可以修改透明度)
在摄像机上绑定下面这个脚本unity射线检测检测不到物体创作人,思路是:从主角的位置向摄像机发射一条射线,射线检测到的所有碰撞体都应该隐藏掉。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CameraAvoidBlock : MonoBehaviour {
//摄像机观察目标,即主角
public Transform Target;
public Transform LookAt;
//在摄像机和主角之间的物体
List lastHitObjs;
List hitObjs;
void LateUpdate() {
if (Target == null || LookAt == null) return;//主角为空,就不作任何操作
AvoidViewBlock();//在Update函数中检测是否有物体挡住主角
}
void AvoidViewBlock()
{
Vector3 ori = Target.position+Vector3.up*0.2f;//射线起点是主角位置偏上一点
Vector3 dir = (transform.position-Target.position).normalized; //射线方向从主角指向摄像机,向量要进行单位化
Debug.DrawRay(ori,dir);//运行时,在场景中观察射线是否正常
RaycastHit[] raycastHits=Physics.RaycastAll(ori,dir,1000f);//获取射线的raycast hit数组
//每一帧射中的物体都要重新计算,清空物体列表
hitObjs.Clear();
//把除了主角本身以外碰撞到的物体加入到List中
if (raycastHits.Length > 1)
{
for(int i = 0; i < raycastHits.Length; i++)
{
if (raycastHits[i].transform.Equals(Target)) continue;
GameObject go = raycastHits[i].collider.gameObject;
if (go.GetComponent()==null)continue;
hitObjs.Add(go);
//对这些物体进行操作:如降低材质透明度或禁用Renderer
//注意:不能禁用该物体碰撞盒,否则下一帧检测不到该物体,也无法复原
SetMaterialAlpha(raycastHits[i].collider.gameObject,0f);
}
}
//这里的思想是:理论上要把lastHitObjs中的所有物体都恢复
//但是有一些物体这一帧还在遮挡,所以把它们刨去
for(int i = 0; i < lastHitObjs.Count; i++)
{
for(int j = 0; j < hitObjs.Count; j++)
{
if (hitObjs[j] != null)
{
if (hitObjs[j] == lastHitObjs[i])
{
lastHitObjs[i] = null;
}
}
}
}
for(int i = 0; i < lastHitObjs.Count; i++)
{
if (lastHitObjs[i] != null)
{
SetMaterialAlpha(lastHitObjs[i], 1f);//把他们的材质透明度恢复
}
}
//结束之后,更新lastHitObjs
for (int i = 0; i < hitObjs.Count; i++)
{
lastHitObjs.Add(hitObjs[i]);//这次的物体移到上次被碰到的List当中去
}
}
void SetMaterialAlpha(GameObject go,float alpha)
{
Renderer renderer = go.GetComponent();
int matNum= renderer.sharedMaterials.Length;
//SharedMaterials和materials的区别在于:
//改变前者会改变所有用到了这个材质的物体,而后者只改变这个物体
for (int i=0;i
文章来源:https://blog.csdn.net/qq_36622009/article/details/83240594