树没有挡住主角前、树挡住后变透明

树没有挡住主角前、树挡住后变透明

参考了这两位的文章:

最终效果:树没有挡住主角前、树挡住主角后变透明

unity射线检测获得3d物体_unity检测射线碰到的物体_unity射线检测检测不到物体

unity检测射线碰到的物体_unity射线检测检测不到物体_unity射线检测获得3d物体

下面是我的解决方案:

需要注意的设置:需要变透明的物体一定要有碰撞盒(可以被射线检测到)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

如有侵权,请致邮箱service@joyindie.com联系我们