using System.Collections.Generic; using DG.Tweening; using UnityEngine; public class UI_SelectSong_EnterAnim : MonoBehaviour { [Header("Play")] [SerializeField] bool playOnEnable = true; [SerializeField] float delay = 0.05f; [Header("Timing")] [SerializeField] float panelTime = 0.55f; [SerializeField] float titleTime = 0.4f; [SerializeField] float listTime = 0.55f; [SerializeField] float buttonTime = 0.35f; [SerializeField] float stagger = 0.06f; [SerializeField] Ease ease = Ease.OutCubic; [Header("Offsets")] [SerializeField] float slideX = 180f; [SerializeField] float slideY = 120f; [SerializeField] float bgScaleFrom = 1.06f; RectTransform root; RectTransform bg; RectTransform leftDlc; RectTransform songScroll; RectTransform rightInfos; RectTransform songTitle; RectTransform dlcTitle; RectTransform quickEnter; RectTransform enterDetail; RectTransform difficultyGroup; readonly Dictionary basePos = new(); readonly Dictionary baseScale = new(); readonly List difficultyItems = new(); Sequence enterSeq; void Awake() { CacheRefs(); } void OnEnable() { if (playOnEnable) { Play(); } } public void Play() { CacheRefs(); KillTweens(); Prepare(); BuildSequence(); } public void SetDelay(float value) { delay = Mathf.Max(0f, value); } void CacheRefs() { if (root == null) { root = transform.parent as RectTransform; if (root == null) { Canvas canvas = Object.FindAnyObjectByType(); if (canvas != null) { root = canvas.transform as RectTransform; } } } if (root == null) { return; } bg = bg != null ? bg : FindRect(root, "BG"); leftDlc = leftDlc != null ? leftDlc : FindRect(root, "left_select_dlc"); songScroll = songScroll != null ? songScroll : FindRect(root, "SongScrollView"); rightInfos = rightInfos != null ? rightInfos : FindRect(root, "rightInfos"); songTitle = songTitle != null ? songTitle : FindRect(root, "songSVtitle"); dlcTitle = dlcTitle != null ? dlcTitle : FindRect(root, "dlcSVtitle"); quickEnter = quickEnter != null ? quickEnter : FindRect(root, "quickEnterThisSong"); enterDetail = enterDetail != null ? enterDetail : FindRect(root, "enter detail page"); difficultyGroup = difficultyGroup != null ? difficultyGroup : FindRect(root, "difficultyBtnInfos"); difficultyItems.Clear(); if (difficultyGroup != null) { for (int i = 0; i < difficultyGroup.childCount; i++) { RectTransform child = difficultyGroup.GetChild(i) as RectTransform; if (child != null) { difficultyItems.Add(child); } } difficultyItems.Sort((a, b) => a.anchoredPosition.x.CompareTo(b.anchoredPosition.x)); } } RectTransform FindRect(Transform rootTransform, string name) { if (rootTransform == null || string.IsNullOrEmpty(name)) { return null; } Transform direct = rootTransform.Find(name); if (direct != null) { return direct as RectTransform; } RectTransform[] rects = rootTransform.GetComponentsInChildren(true); for (int i = 0; i < rects.Length; i++) { if (rects[i] != null && rects[i].name == name) { return rects[i]; } } return null; } void CacheBase(RectTransform rect) { if (rect == null) { return; } if (!basePos.ContainsKey(rect)) { basePos[rect] = rect.anchoredPosition; } if (!baseScale.ContainsKey(rect)) { baseScale[rect] = rect.localScale; } } void Prepare() { if (bg != null && bg.gameObject.activeInHierarchy) { CacheBase(bg); bg.localScale = baseScale[bg] * bgScaleFrom; CanvasGroup group = EnsureCanvasGroup(bg); if (group != null) group.alpha = 0f; } PrepareSlide(leftDlc, Vector2.left * slideX); PrepareSlide(songScroll, Vector2.down * slideY); PrepareSlide(rightInfos, Vector2.right * slideX); PrepareSlide(songTitle, Vector2.up * (slideY * 0.6f)); PrepareSlide(dlcTitle, Vector2.left * (slideX * 0.6f)); PrepareScale(quickEnter, 0.92f); PrepareScale(enterDetail, 0.92f); for (int i = 0; i < difficultyItems.Count; i++) { PrepareSlide(difficultyItems[i], Vector2.down * (slideY * 0.35f)); } } void PrepareSlide(RectTransform rect, Vector2 offset) { if (rect == null) { return; } CacheBase(rect); rect.anchoredPosition = basePos[rect] + offset; CanvasGroup group = EnsureCanvasGroup(rect); if (group != null) group.alpha = 0f; } void PrepareScale(RectTransform rect, float scaleMul) { if (rect == null) { return; } CacheBase(rect); rect.localScale = baseScale[rect] * scaleMul; CanvasGroup group = EnsureCanvasGroup(rect); if (group != null) group.alpha = 0f; } void BuildSequence() { enterSeq = DOTween.Sequence(); float t = delay; if (bg != null && bg.gameObject.activeInHierarchy) { CanvasGroup group = EnsureCanvasGroup(bg); if (group != null) { enterSeq.Insert(t, group.DOFade(1f, panelTime).SetEase(ease)); } if (baseScale.TryGetValue(bg, out Vector3 scale)) { enterSeq.Insert(t, bg.DOScale(scale, panelTime).SetEase(ease)); } } InsertSlide(leftDlc, t + 0.05f, panelTime); InsertSlide(dlcTitle, t + 0.08f, titleTime); InsertSlide(songTitle, t + 0.1f, titleTime); InsertSlide(songScroll, t + 0.12f, listTime); InsertSlide(rightInfos, t + 0.15f, panelTime); if (difficultyItems.Count > 0) { float start = t + 0.25f; for (int i = 0; i < difficultyItems.Count; i++) { InsertSlide(difficultyItems[i], start + i * stagger, buttonTime); } } InsertScale(enterDetail, t + 0.35f, buttonTime); InsertScale(quickEnter, t + 0.38f, buttonTime); } void InsertSlide(RectTransform rect, float at, float time) { if (rect == null) { return; } CacheBase(rect); if (basePos.TryGetValue(rect, out Vector2 pos)) { enterSeq.Insert(at, rect.DOAnchorPos(pos, time).SetEase(ease)); } CanvasGroup group = EnsureCanvasGroup(rect); if (group != null) { enterSeq.Insert(at, group.DOFade(1f, time).SetEase(ease)); } } void InsertScale(RectTransform rect, float at, float time) { if (rect == null) { return; } CacheBase(rect); if (baseScale.TryGetValue(rect, out Vector3 scale)) { enterSeq.Insert(at, rect.DOScale(scale, time).SetEase(ease)); } CanvasGroup group = EnsureCanvasGroup(rect); if (group != null) { enterSeq.Insert(at, group.DOFade(1f, time).SetEase(ease)); } } CanvasGroup EnsureCanvasGroup(RectTransform rect) { if (rect == null) { return null; } CanvasGroup group = rect.GetComponent(); if (group == null) { group = rect.gameObject.AddComponent(); } return group; } void KillTweens() { if (enterSeq != null) { enterSeq.Kill(); enterSeq = null; } } }