132 lines
4.0 KiB
C#
132 lines
4.0 KiB
C#
using UnityEngine;
|
|
|
|
/// <summary>
|
|
/// Runtime driver for materials made from the Rainbow-Cats dissolve / HDR-outline shaders.
|
|
/// Attach to any Renderer and it will animate the shader's exposed properties so you get the
|
|
/// dissolve fade or the pulsing HDR outline without touching material properties by hand.
|
|
///
|
|
/// Works on an instanced copy of the material via MaterialPropertyBlock, so multiple objects
|
|
/// sharing one material can dissolve independently.
|
|
/// </summary>
|
|
[RequireComponent(typeof(Renderer))]
|
|
public class DissolveEffectController : MonoBehaviour
|
|
{
|
|
public enum Effect
|
|
{
|
|
/// <summary>Drives "_Fade": 0 = fully dissolved/hidden, 1 = fully visible (Dissolve shader).</summary>
|
|
Dissolve,
|
|
/// <summary>Drives "_Emission": pulses the HDR outline glow (HDR Outline shader).</summary>
|
|
OutlinePulse
|
|
}
|
|
|
|
[Header("Which effect")]
|
|
public Effect effect = Effect.Dissolve;
|
|
|
|
[Header("Dissolve")]
|
|
[Tooltip("If true, the object animates from dissolved -> visible on enable. If false, visible -> dissolved.")]
|
|
public bool appear = true;
|
|
|
|
[Tooltip("Seconds the dissolve animation takes.")]
|
|
public float dissolveDuration = 1.5f;
|
|
|
|
[Tooltip("If true the animation plays automatically on enable. Otherwise call Play().")]
|
|
public bool playOnEnable = true;
|
|
|
|
[Header("Outline pulse")]
|
|
[Tooltip("Min emission intensity for the outline pulse.")]
|
|
public float pulseMin = 1f;
|
|
|
|
[Tooltip("Max emission intensity for the outline pulse.")]
|
|
public float pulseMax = 6f;
|
|
|
|
[Tooltip("Pulses per second.")]
|
|
public float pulseSpeed = 1.5f;
|
|
|
|
// Property IDs from the shader graphs' exposed reference names.
|
|
private static readonly int FadeId = Shader.PropertyToID("_Fade");
|
|
private static readonly int EmissionId = Shader.PropertyToID("_Emission");
|
|
|
|
private Renderer targetRenderer;
|
|
private MaterialPropertyBlock block;
|
|
private float timer;
|
|
private bool playing;
|
|
|
|
// Track on-screen visibility so the continuous OutlinePulse write is skipped when the
|
|
// renderer is offscreen (nothing would be seen anyway). Assume visible until Unity tells
|
|
// us otherwise, so effects on objects that never entered the culling system still animate.
|
|
private bool isVisible = true;
|
|
|
|
private void OnBecameVisible() { isVisible = true; }
|
|
private void OnBecameInvisible() { isVisible = false; }
|
|
|
|
private void Awake()
|
|
{
|
|
targetRenderer = GetComponent<Renderer>();
|
|
block = new MaterialPropertyBlock();
|
|
}
|
|
|
|
private void OnEnable()
|
|
{
|
|
if (playOnEnable)
|
|
{
|
|
Play();
|
|
}
|
|
}
|
|
|
|
/// <summary>Restart the effect from the beginning.</summary>
|
|
public void Play()
|
|
{
|
|
timer = 0f;
|
|
playing = true;
|
|
}
|
|
|
|
/// <summary>Set the dissolve amount directly (0 = hidden, 1 = visible) and stop animating.</summary>
|
|
public void SetFade(float value)
|
|
{
|
|
playing = false;
|
|
targetRenderer.GetPropertyBlock(block);
|
|
block.SetFloat(FadeId, Mathf.Clamp01(value));
|
|
targetRenderer.SetPropertyBlock(block);
|
|
}
|
|
|
|
private void Update()
|
|
{
|
|
if (effect == Effect.OutlinePulse)
|
|
{
|
|
if (isVisible) UpdatePulse();
|
|
return;
|
|
}
|
|
|
|
if (playing)
|
|
{
|
|
UpdateDissolve();
|
|
}
|
|
}
|
|
|
|
private void UpdateDissolve()
|
|
{
|
|
timer += Time.deltaTime;
|
|
float t = dissolveDuration > 0f ? Mathf.Clamp01(timer / dissolveDuration) : 1f;
|
|
float fade = appear ? t : 1f - t;
|
|
|
|
targetRenderer.GetPropertyBlock(block);
|
|
block.SetFloat(FadeId, fade);
|
|
targetRenderer.SetPropertyBlock(block);
|
|
|
|
if (t >= 1f)
|
|
{
|
|
playing = false;
|
|
}
|
|
}
|
|
|
|
private void UpdatePulse()
|
|
{
|
|
float wave = (Mathf.Sin(Time.time * pulseSpeed * Mathf.PI * 2f) + 1f) * 0.5f;
|
|
float emission = Mathf.Lerp(pulseMin, pulseMax, wave);
|
|
|
|
targetRenderer.GetPropertyBlock(block);
|
|
block.SetFloat(EmissionId, emission);
|
|
targetRenderer.SetPropertyBlock(block);
|
|
}
|
|
}
|