using UnityEngine; using UnityEngine.UI; [RequireComponent(typeof(Graphic))] public class UIDissolveController : MonoBehaviour { public Material materialTemplate; [Range(0f, 1f)] public float dissolveAmount = 1f; public float dissolveSpeed = 1f; public bool isDissolving; [ColorUsage(true, true)] public Color dissolveOutColor = Color.magenta; [ColorUsage(true, true)] public Color dissolveInColor = Color.white; private Graphic graphic; private Material runtimeMaterial; private static readonly int DissolveAmountId = Shader.PropertyToID("_DissolveAmount"); private static readonly int DissolveColorId = Shader.PropertyToID("_DissolveColor"); private void Awake() { graphic = GetComponent(); EnsureRuntimeMaterial(); ApplyProperties(); } private void OnEnable() { EnsureRuntimeMaterial(); ApplyProperties(); } private void OnDestroy() { if (runtimeMaterial != null) { if (graphic != null && graphic.material == runtimeMaterial) { graphic.material = null; } Destroy(runtimeMaterial); } } private void Update() { if (runtimeMaterial == null) { return; } if (isDissolving) { dissolveAmount = Mathf.Max(0f, dissolveAmount - Time.deltaTime * dissolveSpeed); runtimeMaterial.SetColor(DissolveColorId, dissolveOutColor); } else { dissolveAmount = Mathf.Min(1f, dissolveAmount + Time.deltaTime * dissolveSpeed); runtimeMaterial.SetColor(DissolveColorId, dissolveInColor); } runtimeMaterial.SetFloat(DissolveAmountId, dissolveAmount); } public void SetDissolveAmount(float value) { dissolveAmount = Mathf.Clamp01(value); ApplyProperties(); } public void DissolveOut() { isDissolving = true; ApplyProperties(); } public void DissolveIn() { isDissolving = false; ApplyProperties(); } private void EnsureRuntimeMaterial() { if (graphic == null) { graphic = GetComponent(); } if (graphic == null) { return; } Material source = materialTemplate != null ? materialTemplate : (graphic.material != null ? graphic.material : graphic.defaultMaterial); if (source == null) { return; } if (runtimeMaterial != null && runtimeMaterial.shader == source.shader) { if (graphic.material != runtimeMaterial) { graphic.material = runtimeMaterial; } return; } if (runtimeMaterial != null) { Destroy(runtimeMaterial); } runtimeMaterial = new Material(source); runtimeMaterial.name = source.name + " (UI Runtime)"; graphic.material = runtimeMaterial; } private void ApplyProperties() { if (runtimeMaterial == null) { return; } runtimeMaterial.SetFloat(DissolveAmountId, dissolveAmount); runtimeMaterial.SetColor(DissolveColorId, isDissolving ? dissolveOutColor : dissolveInColor); } }