using UnityEngine; using System.Collections.Generic; public class FadeAlphaController : MonoBehaviour { [Header("Fade Settings")] [Tooltip("Animation curve to control fade alpha over time (0-1)")] public AnimationCurve fadeCurve = AnimationCurve.Linear(0f, 1f, 1f, 0f); [Tooltip("Duration of the fade animation in seconds")] [Range(0.1f, 10f)] public float duration = 1f; [Tooltip("Auto play on start")] public bool autoPlay = false; [Tooltip("Loop the animation")] public bool loop = false; [Header("Material Settings")] [Tooltip("Shader property name for fade alpha")] public string fadeAlphaPropertyName = "_fadeAlpha"; [Header("Runtime Info")] [SerializeField] [Tooltip("Current time in the animation")] private float currentTime = 0f; [SerializeField] [Tooltip("Is the animation currently playing")] private bool isPlaying = false; private List cachedRenderers = new List(); private Dictionary propertyBlocks = new Dictionary(); private int fadeAlphaPropertyID; private void Awake() { fadeAlphaPropertyID = Shader.PropertyToID(fadeAlphaPropertyName); CacheMaterials(); } private void Start() { if (autoPlay) { Play(); } } private void Update() { if (!isPlaying) return; currentTime += Time.deltaTime; float normalizedTime = Mathf.Clamp01(currentTime / duration); ApplyFadeAlpha(fadeCurve.Evaluate(normalizedTime)); if (currentTime >= duration) { currentTime = 0f; isPlaying = loop; } } private void CacheMaterials() { cachedRenderers.Clear(); propertyBlocks.Clear(); Renderer[] allRenderers = GetComponentsInChildren(true); foreach (Renderer renderer in allRenderers) { if (renderer != null && HasFadeAlphaProperty(renderer)) { cachedRenderers.Add(renderer); MaterialPropertyBlock mpb = new MaterialPropertyBlock(); renderer.GetPropertyBlock(mpb); propertyBlocks[renderer] = mpb; } } // Debug.Log($"[FadeAlphaController] Cached {cachedRenderers.Count} renderers with {fadeAlphaPropertyName} property"); } private bool HasFadeAlphaProperty(Renderer renderer) { if (renderer.sharedMaterials == null) return false; foreach (Material mat in renderer.sharedMaterials) { if (mat != null && mat.HasProperty(fadeAlphaPropertyID)) { return true; } } return false; } public void ApplyFadeAlpha(float alpha) { foreach (Renderer renderer in cachedRenderers) { if (renderer != null && propertyBlocks.TryGetValue(renderer, out MaterialPropertyBlock mpb)) { mpb.SetFloat(fadeAlphaPropertyID, alpha); renderer.SetPropertyBlock(mpb); } } } public void Toggle() { if (isPlaying) Stop(); else Play(); } public void Play() { currentTime = 0f; ApplyFadeAlpha(fadeCurve.Evaluate(currentTime)); isPlaying = true; } public void Pause() { isPlaying = false; } public void Resume() { isPlaying = true; } public void Stop() { isPlaying = false; currentTime = 0f; ApplyFadeAlpha(fadeCurve.Evaluate(0f)); } public void SetFadeAlpha(float alpha) { ApplyFadeAlpha(Mathf.Clamp01(alpha)); } public void RefreshMaterials() { CacheMaterials(); if (isPlaying) { float normalizedTime = Mathf.Clamp01(currentTime / duration); ApplyFadeAlpha(fadeCurve.Evaluate(normalizedTime)); } } public float GetCurrentFadeAlpha() { float normalizedTime = Mathf.Clamp01(currentTime / duration); return fadeCurve.Evaluate(normalizedTime); } private void OnValidate() { if (duration <= 0f) { duration = 0.1f; } } private void OnDestroy() { cachedRenderers.Clear(); propertyBlocks.Clear(); } }