先看下效果
视频有压缩,效果有点不对,下面是正确的效果
先上两段代码
using System; using System.Collections.Generic; using UnityEngine; public class FadingObject : MonoBehaviour, IEquatable<FadingObject> { public List<Renderer> Renderers = new List<Renderer>(); public Vector3 Position; public List<Material> Materials = new List<Material>(); [HideInInspector] public float InitialAlpha; //public float InitialFadeScale; private void Awake() { Position = transform.position; if (Renderers.Count == 0) { Renderers.AddRange(GetComponentsInChildren<Renderer>()); } foreach(Renderer renderer in Renderers) { Materials.AddRange(renderer.materials); } InitialAlpha = Materials[0].color.a; Materials[0].SetFloat("_DitherThreshold", 1f); } public bool Equals(FadingObject other) { return Position.Equals(other.Position); } public override int GetHashCode() { return Position.GetHashCode(); } }
using System.Collections; using System.Collections.Generic; using UnityEngine; public class FadeObjectBlockingObject : MonoBehaviour { [SerializeField] private LayerMask LayerMask; [SerializeField] private Transform Target; [SerializeField] private Camera Camera; [SerializeField] [Range(0, 1f)] private float FadedAlpha = 0.33f; [SerializeField] private bool RetainShadows = true; [SerializeField] private Vector3 TargetPositionOffset = Vector3.up; [SerializeField] private float FadeSpeed = 1; [Header("Read Only Data")] [SerializeField] private List<FadingObject> ObjectsBlockingView = new List<FadingObject>(); private Dictionary<FadingObject, Coroutine> RunningCoroutines = new Dictionary<FadingObject, Coroutine>(); private RaycastHit[] Hits = new RaycastHit[10]; private void OnEnable() { StartCoroutine(CheckForObjects()); } private IEnumerator CheckForObjects() { while (true) { int hits = Physics.RaycastNonAlloc( Camera.transform.position, (Target.transform.position + TargetPositionOffset - Camera.transform.position).normalized, Hits, Vector3.Distance(Camera.transform.position, Target.transform.position + TargetPositionOffset), LayerMask ); if (hits > 0) { for (int i = 0; i < hits; i++) { FadingObject fadingObject = GetFadingObjectFromHit(Hits[i]); if (fadingObject != null && !ObjectsBlockingView.Contains(fadingObject)) { if (RunningCoroutines.ContainsKey(fadingObject)) { if (RunningCoroutines[fadingObject] != null) { StopCoroutine(RunningCoroutines[fadingObject]); } RunningCoroutines.Remove(fadingObject); } RunningCoroutines.Add(fadingObject, StartCoroutine(FadeObjectOut(fadingObject))); ObjectsBlockingView.Add(fadingObject); } } } FadeObjectsNoLongerBeingHit(); ClearHits(); yield return null; } } private void FadeObjectsNoLongerBeingHit() { List<FadingObject> objectsToRemove = new List<FadingObject>(ObjectsBlockingView.Count); foreach (FadingObject fadingObject in ObjectsBlockingView) { bool objectIsBeingHit = false; for (int i = 0; i < Hits.Length; i++) { FadingObject hitFadingObject = GetFadingObjectFromHit(Hits[i]); if (hitFadingObject != null && fadingObject == hitFadingObject) { objectIsBeingHit = true; break; } } if (!objectIsBeingHit) { if (RunningCoroutines.ContainsKey(fadingObject)) { if (RunningCoroutines[fadingObject] != null) { StopCoroutine(RunningCoroutines[fadingObject]); } RunningCoroutines.Remove(fadingObject); } RunningCoroutines.Add(fadingObject, StartCoroutine(FadeObjectIn(fadingObject))); objectsToRemove.Add(fadingObject); } } foreach(FadingObject removeObject in objectsToRemove) { ObjectsBlockingView.Remove(removeObject); } } private IEnumerator FadeObjectOut(FadingObject FadingObject) { foreach (Material material in FadingObject.Materials) { material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.SrcAlpha); material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha); material.SetInt("_ZWrite", 0); material.SetInt("_Surface", 1); material.renderQueue = (int)UnityEngine.Rendering.RenderQueue.Transparent; material.SetShaderPassEnabled("DepthOnly", false); material.SetShaderPassEnabled("SHADOWCASTER", RetainShadows); material.SetOverrideTag("RenderType", "Transparent"); material.EnableKeyword("_SURFACE_TYPE_TRANSPARENT"); material.EnableKeyword("_ALPHAPREMULTIPLY_ON"); } float time = 0; while (FadingObject.Materials[0].color.a > FadedAlpha) { foreach (Material material in FadingObject.Materials) { if (material.HasProperty("_BaseColor")) { float a = Mathf.Lerp(FadingObject.InitialAlpha, FadedAlpha, time * FadeSpeed); material.color = new Color( material.color.r, material.color.g, material.color.b, a ); //print("_1"); //Setting fade value material.SetFloat("_DitherThreshold", a); } } time += Time.deltaTime; yield return null; } if (RunningCoroutines.ContainsKey(FadingObject)) { StopCoroutine(RunningCoroutines[FadingObject]); RunningCoroutines.Remove(FadingObject); } } private IEnumerator FadeObjectIn(FadingObject FadingObject) { float time = 0; while (FadingObject.Materials[0].color.a < FadingObject.InitialAlpha) { foreach (Material material in FadingObject.Materials) { if (material.HasProperty("_BaseColor")) { float a = Mathf.Lerp(FadedAlpha, FadingObject.InitialAlpha, time * FadeSpeed); material.color = new Color( material.color.r, material.color.g, material.color.b, a ); //Setting fade value material.SetFloat("_DitherThreshold", a); } } time += Time.deltaTime; yield return null; } foreach (Material material in FadingObject.Materials) { material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One); material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero); material.SetInt("_ZWrite", 1); material.SetInt("_Surface", 0); material.renderQueue = (int)UnityEngine.Rendering.RenderQueue.Geometry; material.SetShaderPassEnabled("DepthOnly", true); material.SetShaderPassEnabled("SHADOWCASTER", true); material.SetOverrideTag("RenderType", "Opaque"); material.DisableKeyword("_SURFACE_TYPE_TRANSPARENT"); material.DisableKeyword("_ALPHAPREMULTIPLY_ON"); } if (RunningCoroutines.ContainsKey(FadingObject)) { StopCoroutine(RunningCoroutines[FadingObject]); RunningCoroutines.Remove(FadingObject); } } private void ClearHits() { System.Array.Clear(Hits, 0, Hits.Length); } private FadingObject GetFadingObjectFromHit(RaycastHit Hit) { return Hit.collider != null ? Hit.collider.GetComponent<FadingObject>() : null; } }
放一个自动抓取场景中的物体然后再实现遮挡处理的脚本,这个主要是用在main camera需要从全局调用的场景
using System.Collections; using System.Collections.Generic; using UnityEngine; public class FadeObjectBlockingObject : MonoBehaviour { [SerializeField] private LayerMask LayerMask; [SerializeField] private Transform Target; [SerializeField] private Camera Camera; [SerializeField] [Range(0, 1f)] private float FadedAlpha = 0.33f; [SerializeField] private bool RetainShadows = true; [SerializeField] private Vector3 TargetPositionOffset = Vector3.up; [SerializeField] private float FadeSpeed = 1; [Header("Read Only Data")] [SerializeField] private List<FadingObject> ObjectsBlockingView = new List<FadingObject>(); private Dictionary<FadingObject, Coroutine> RunningCoroutines = new Dictionary<FadingObject, Coroutine>(); private RaycastHit[] Hits = new RaycastHit[10]; void Start() { this.Camera = Camera.main; this.Target = this.transform; if (this.transform.parent.name == "ePlayer") { StartCoroutine(CheckForObjects()); } } private void OnEnable() { } private IEnumerator CheckForObjects() { while (true) { int hits = Physics.RaycastNonAlloc( Camera.transform.position, (Target.transform.position + TargetPositionOffset - Camera.transform.position).normalized, Hits, Vector3.Distance(Camera.transform.position, Target.transform.position + TargetPositionOffset), LayerMask ); // Gizmos.DrawLine(Camera.transform.position, Target.transform.position); // Debug.DrawLine(Camera.transform.position, Target.transform.position , Color.red, 0.5f ); if (hits > 0) { for (int i = 0; i < hits; i++) { FadingObject fadingObject = GetFadingObjectFromHit(Hits[i]); if (fadingObject != null && !ObjectsBlockingView.Contains(fadingObject)) { if (RunningCoroutines.ContainsKey(fadingObject)) { if (RunningCoroutines[fadingObject] != null) { StopCoroutine(RunningCoroutines[fadingObject]); } RunningCoroutines.Remove(fadingObject); } RunningCoroutines.Add(fadingObject, StartCoroutine(FadeObjectOut(fadingObject))); ObjectsBlockingView.Add(fadingObject); } } } FadeObjectsNoLongerBeingHit(); ClearHits(); yield return null; } } private void FadeObjectsNoLongerBeingHit() { List<FadingObject> objectsToRemove = new List<FadingObject>(ObjectsBlockingView.Count); foreach (FadingObject fadingObject in ObjectsBlockingView) { bool objectIsBeingHit = false; for (int i = 0; i < Hits.Length; i++) { FadingObject hitFadingObject = GetFadingObjectFromHit(Hits[i]); if (hitFadingObject != null && fadingObject == hitFadingObject) { objectIsBeingHit = true; break; } } if (!objectIsBeingHit) { if (RunningCoroutines.ContainsKey(fadingObject)) { if (RunningCoroutines[fadingObject] != null) { StopCoroutine(RunningCoroutines[fadingObject]); } RunningCoroutines.Remove(fadingObject); } RunningCoroutines.Add(fadingObject, StartCoroutine(FadeObjectIn(fadingObject))); objectsToRemove.Add(fadingObject); } } foreach(FadingObject removeObject in objectsToRemove) { ObjectsBlockingView.Remove(removeObject); } } private IEnumerator FadeObjectOut(FadingObject FadingObject) { foreach (Material material in FadingObject.Materials) { material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.SrcAlpha); material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha); material.SetInt("_ZWrite", 0); material.SetInt("_Surface", 1); material.renderQueue = (int)UnityEngine.Rendering.RenderQueue.Transparent; material.SetShaderPassEnabled("DepthOnly", false); material.SetShaderPassEnabled("SHADOWCASTER", RetainShadows); material.SetOverrideTag("RenderType", "Transparent"); material.EnableKeyword("_SURFACE_TYPE_TRANSPARENT"); material.EnableKeyword("_ALPHAPREMULTIPLY_ON"); } float time = 0; while (FadingObject.Materials[0].color.a > FadedAlpha) { foreach (Material material in FadingObject.Materials) { if (material.HasProperty("_BaseColor")) { float a = Mathf.Lerp(FadingObject.InitialAlpha, FadedAlpha, time * FadeSpeed); material.color = new Color( material.color.r, material.color.g, material.color.b, a ); //print("_1"); //Setting fade value material.SetFloat("_DitherThreshold", a); } } time += Time.deltaTime; yield return null; } if (RunningCoroutines.ContainsKey(FadingObject)) { StopCoroutine(RunningCoroutines[FadingObject]); RunningCoroutines.Remove(FadingObject); } } private IEnumerator FadeObjectIn(FadingObject FadingObject) { float time = 0; while (FadingObject.Materials[0].color.a < FadingObject.InitialAlpha) { foreach (Material material in FadingObject.Materials) { if (material.HasProperty("_BaseColor")) { float a = Mathf.Lerp(FadedAlpha, FadingObject.InitialAlpha, time * FadeSpeed); material.color = new Color( material.color.r, material.color.g, material.color.b, a ); //Setting fade value material.SetFloat("_DitherThreshold", a); } } time += Time.deltaTime; yield return null; } foreach (Material material in FadingObject.Materials) { material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One); material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero); material.SetInt("_ZWrite", 1); material.SetInt("_Surface", 0); material.renderQueue = (int)UnityEngine.Rendering.RenderQueue.Geometry; material.SetShaderPassEnabled("DepthOnly", true); material.SetShaderPassEnabled("SHADOWCASTER", true); material.SetOverrideTag("RenderType", "Opaque"); material.DisableKeyword("_SURFACE_TYPE_TRANSPARENT"); material.DisableKeyword("_ALPHAPREMULTIPLY_ON"); } if (RunningCoroutines.ContainsKey(FadingObject)) { StopCoroutine(RunningCoroutines[FadingObject]); RunningCoroutines.Remove(FadingObject); } } private void ClearHits() { System.Array.Clear(Hits, 0, Hits.Length); } private FadingObject GetFadingObjectFromHit(RaycastHit Hit) { return Hit.collider != null ? Hit.collider.GetComponent<FadingObject>() : null; } }