using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; public class IntroTitleSequence : MonoBehaviour { [System.Serializable] public class IntroSequenceItem { [Header("Info")] public string itemName; [Header("Target")] public GameObject target; [Header("Timing")] public float delay = 0f; public float fadeDuration = 0.6f; [Header("Appear Motion")] [Range(0.1f, 1f)] public float startScaleRatio = 0.92f; public Vector3 startOffset = new Vector3(0f, -0.08f, 0f); [Header("After Appear")] public bool enableFloatingAfterAppear = true; public bool enableParallaxAfterAppear = true; public bool enableButtonPulseAfterAppear = false; } [Header("Sequence")] public bool playOnStart = true; public float globalDelayMultiplier = 1f; public float globalFadeMultiplier = 1f; public List sequenceItems = new List(); [Header("Optional Particle")] public ParticleSystem petalParticle; public float petalStartDelay = 0.2f; private readonly Dictionary originalPositions = new Dictionary(); private readonly Dictionary originalScales = new Dictionary(); private void Start() { if (playOnStart) { PlaySequence(); } } public void PlaySequence() { StopAllCoroutines(); CacheOriginalTransforms(); PrepareAllItems(); StartCoroutine(PlaySequenceRoutine()); } private void CacheOriginalTransforms() { originalPositions.Clear(); originalScales.Clear(); foreach (IntroSequenceItem item in sequenceItems) { if (item == null || item.target == null) continue; originalPositions[item.target] = item.target.transform.localPosition; originalScales[item.target] = item.target.transform.localScale; } } private void PrepareAllItems() { foreach (IntroSequenceItem item in sequenceItems) { if (item == null || item.target == null) continue; GameObject target = item.target; target.SetActive(true); Vector3 originalPosition = originalPositions[target]; Vector3 originalScale = originalScales[target]; target.transform.localPosition = originalPosition + item.startOffset; target.transform.localScale = originalScale * item.startScaleRatio; SetTargetAlpha(target, 0f); SetOptionalMotionScripts(target, false, false, false); } } private IEnumerator PlaySequenceRoutine() { if (petalParticle != null) { petalParticle.Stop(); if (petalStartDelay > 0f) yield return new WaitForSeconds(petalStartDelay); petalParticle.Play(); } foreach (IntroSequenceItem item in sequenceItems) { if (item == null || item.target == null) continue; StartCoroutine(AppearRoutine(item)); } } private IEnumerator AppearRoutine(IntroSequenceItem item) { float delay = Mathf.Max(0f, item.delay * globalDelayMultiplier); float duration = Mathf.Max(0.01f, item.fadeDuration * globalFadeMultiplier); if (delay > 0f) yield return new WaitForSeconds(delay); GameObject target = item.target; Vector3 originalPosition = originalPositions[target]; Vector3 originalScale = originalScales[target]; Vector3 startPosition = originalPosition + item.startOffset; Vector3 startScale = originalScale * item.startScaleRatio; target.transform.localPosition = startPosition; target.transform.localScale = startScale; SetTargetAlpha(target, 0f); float elapsed = 0f; while (elapsed < duration) { elapsed += Time.deltaTime; float t = Mathf.Clamp01(elapsed / duration); float easedT = EaseOutCubic(t); SetTargetAlpha(target, easedT); target.transform.localPosition = Vector3.Lerp(startPosition, originalPosition, easedT); target.transform.localScale = Vector3.Lerp(startScale, originalScale, easedT); yield return null; } SetTargetAlpha(target, 1f); target.transform.localPosition = originalPosition; target.transform.localScale = originalScale; SetOptionalMotionScripts( target, item.enableFloatingAfterAppear, item.enableParallaxAfterAppear, item.enableButtonPulseAfterAppear ); } private void SetTargetAlpha(GameObject target, float alpha) { SpriteRenderer[] spriteRenderers = target.GetComponentsInChildren(true); foreach (SpriteRenderer sr in spriteRenderers) { Color color = sr.color; color.a = alpha; sr.color = color; } Graphic[] graphics = target.GetComponentsInChildren(true); foreach (Graphic graphic in graphics) { Color color = graphic.color; color.a = alpha; graphic.color = color; } CanvasGroup[] canvasGroups = target.GetComponentsInChildren(true); foreach (CanvasGroup canvasGroup in canvasGroups) { canvasGroup.alpha = alpha; } } private void SetOptionalMotionScripts(GameObject target, bool floating, bool parallax, bool buttonPulse) { IntroFloatingLayer[] floatingLayers = target.GetComponentsInChildren(true); foreach (IntroFloatingLayer layer in floatingLayers) { layer.enabled = floating; } IntroParallaxLayer[] parallaxLayers = target.GetComponentsInChildren(true); foreach (IntroParallaxLayer layer in parallaxLayers) { layer.enabled = parallax; } IntroButtonPulse[] buttonPulses = target.GetComponentsInChildren(true); foreach (IntroButtonPulse pulse in buttonPulses) { pulse.enabled = buttonPulse; } } private float EaseOutCubic(float t) { return 1f - Mathf.Pow(1f - t, 3f); } }