using System.Collections.Generic;
using UnityEngine;
namespace DestroyIt
{
///
/// Attach this script to any object that has a transparent shader on its mesh renderer.
///
/// Also, you can attach this script to a destroyed prefab that has child "debris" objects. Example: a broken wall object that
/// is composed of multiple child rubble pieces. This script will fade-out and clean up all the child rubble pieces for you.
///
public class FadeOut : MonoBehaviour
{
[Range(0f, 30f)]
public float afterSeconds = 6f; // seconds to wait before starting the fade.
[Range(0f, 10f)]
public float fadeLength = 2f; // how long (in seconds) to fade-out objects before destroying them.
private List objectsToFade;
private float timeLeft;
private bool isInitialized;
private bool isBeingDestroyed;
void Start()
{
timeLeft = afterSeconds;
isInitialized = true;
MeshRenderer[] meshRenderers = transform.GetComponentsInChildren();
if (meshRenderers.Length == 0)
{
Debug.LogWarning("FadeOut: No MeshRenderers found under \"" + transform.name + "\". Cannot fade out.");
Destroy(this);
}
else
{
// Collect all the objects to fade into a list.
objectsToFade = new List();
for (int i = 0; i < meshRenderers.Length; i++)
{
objectsToFade.Add(new ObjectToFade()
{
MeshRenderer = meshRenderers[i],
Colliders = meshRenderers[i].GetComponentsInChildren(),
Rigidbody = meshRenderers[i].GetComponent(),
CanBeFaded = true
});
}
}
}
void OnEnable()
{
timeLeft = afterSeconds;
}
void Update()
{
if (!isInitialized || isBeingDestroyed) return;
timeLeft -= Time.deltaTime;
if (timeLeft <= 0)
{
if (timeLeft <= -1*fadeLength)
{
isBeingDestroyed = true;
Destroy(transform.gameObject);
}
else
Fade();
}
}
private void StripColliders(ObjectToFade obj)
{
// Try to strip Colliders
if (obj.Colliders.Length == 0)
obj.IsStripped = true;
else
{
for (int i=0; iFade this object and its children one step towards invisible.
private void Fade()
{
foreach (ObjectToFade obj in objectsToFade)
{
if (obj.MeshRenderer == null) continue;
// Try to strip Rigidbody and Colliders
if (!obj.IsStripped)
{
if (obj.Rigidbody == null)
{
// No Rigidbody, so try to strip Colliders
StripColliders(obj);
}
else if (obj.Rigidbody.IsSleeping())
{
// Rigidbody is sleeping, so destroy it and then strip Colliders
Destroy(obj.Rigidbody);
StripColliders(obj);
}
// Else Rigidbody isn't sleeping, so leave it alone for now.
}
if (!obj.IsTransparencyChecked)
{
Material[] mats = obj.MeshRenderer.materials;
for (int i = 0; i < mats.Length; i++)
{
// If the material on the object doesn't have a transparency property...
if (!mats[i].HasProperty("_Transparency"))
{
// Try to find the appropriate "Transparent" version of its shader.
mats[i].shader = mats[i].shader.GetTransparentVersion();
mats[i].SetFloat("_Transparency", 0f);
}
}
obj.MeshRenderer.materials = mats;
obj.IsTransparencyChecked = true;
}
for (int i = 0; i < obj.MeshRenderer.materials.Length; i++)
{
float currTransparency = obj.MeshRenderer.materials[i].GetFloat("_Transparency");
if (currTransparency >= 1f)
continue;
currTransparency += Mathf.Clamp01(Time.deltaTime / fadeLength);
obj.MeshRenderer.materials[i].SetFloat("_Transparency", currTransparency);
}
}
}
}
public class ObjectToFade
{
public MeshRenderer MeshRenderer { get; set; }
/// Are the rigidbody and colliders stripped from this object?
public bool IsStripped { get; set; }
public bool CanBeFaded { get; set; }
public Rigidbody Rigidbody { get; set; }
public Collider[] Colliders { get; set; }
public bool IsTransparencyChecked { get; set; }
}
public static class ShaderExtensions
{
public static Shader GetTransparentVersion(this Shader currentShader)
{
Shader transShader;
// Try to find the appropriate "Transparent" version of the shader.
if (currentShader.name.Contains("DestroyIt/"))
transShader = Shader.Find(currentShader.name.Replace("DestroyIt/", "DestroyIt/Transparent"));
else
transShader = Shader.Find("DestroyIt/Transparent" + currentShader.name.Replace(" ", ""));
if (transShader != null)
return transShader;
// Transparent version of shader not found. Try to fallback on DestroyIt/TransparentDiffuse.
transShader = Shader.Find("DestroyIt/TransparentDiffuse");
if (transShader != null)
return transShader;
// if no transparency shader could be found, log an error and destroy this script
Debug.LogError("DestroyIt: No progressive damage transparency shader could be found. Cannot fade out material with shader \"" + currentShader.name + "\" object.");
return currentShader;
}
}
}