using DG.Tweening; using UnityEngine; [DisallowMultipleComponent] public class UI_SettingsPanelEnterAnim : MonoBehaviour { [SerializeField] private RectTransform moveTarget; [SerializeField] private CanvasGroup fadeTarget; [SerializeField] private bool playOnEnable = true; [SerializeField] private float enterDuration = 0.3f; [SerializeField] private float exitDuration = 0.18f; [SerializeField] private float fromOffsetY = 32f; [SerializeField] private Ease enterEase = Ease.OutCubic; [SerializeField] private Ease exitEase = Ease.InCubic; [SerializeField] private bool useUnscaledTime = true; private Sequence enterSequence; private bool basePosCached; private Vector2 basePos; private void Awake() { AutoWire(); CacheBasePos(); } private void OnEnable() { if (playOnEnable) Play(); } private void OnDisable() { KillTween(); ResetToBase(); } public void Play() { AutoWire(); CacheBasePos(); if (moveTarget == null || fadeTarget == null) return; KillTween(); bool canAnimateTransform = !UI_OrderedEntryAnimator.IsLayoutSensitive(moveTarget); if (canAnimateTransform) { moveTarget.anchoredPosition = basePos - new Vector2(0f, Mathf.Abs(fromOffsetY)); } fadeTarget.alpha = 0f; fadeTarget.interactable = false; fadeTarget.blocksRaycasts = false; enterSequence = DOTween.Sequence().SetUpdate(useUnscaledTime); if (canAnimateTransform) { enterSequence.Join(moveTarget.DOAnchorPos(basePos, Mathf.Max(0.01f, enterDuration)).SetEase(enterEase)); } enterSequence.Join(fadeTarget.DOFade(1f, Mathf.Max(0.01f, enterDuration)).SetEase(Ease.OutCubic)); enterSequence.OnComplete(() => { fadeTarget.interactable = true; fadeTarget.blocksRaycasts = true; enterSequence = null; }); enterSequence.OnKill(() => { ResetToBase(); enterSequence = null; }); } public void PlayExitThen(System.Action onComplete) { AutoWire(); CacheBasePos(); if (moveTarget == null || fadeTarget == null) { onComplete?.Invoke(); return; } KillTween(); fadeTarget.interactable = false; fadeTarget.blocksRaycasts = false; Vector2 targetPos = basePos - new Vector2(0f, Mathf.Abs(fromOffsetY)); float duration = Mathf.Max(0.01f, exitDuration); bool canAnimateTransform = !UI_OrderedEntryAnimator.IsLayoutSensitive(moveTarget); enterSequence = DOTween.Sequence().SetUpdate(useUnscaledTime); if (canAnimateTransform) { enterSequence.Join(moveTarget.DOAnchorPos(targetPos, duration).SetEase(exitEase)); } enterSequence.Join(fadeTarget.DOFade(0f, duration).SetEase(Ease.InCubic)); enterSequence.OnComplete(() => { enterSequence = null; ResetToBase(); onComplete?.Invoke(); }); enterSequence.OnKill(() => { ResetToBase(); enterSequence = null; }); } private void AutoWire() { if (moveTarget == null) { moveTarget = transform as RectTransform; if (moveTarget == null) moveTarget = GetComponentInChildren(true); } if (fadeTarget == null) fadeTarget = GetComponent(); if (fadeTarget == null) fadeTarget = gameObject.AddComponent(); } private void CacheBasePos() { if (moveTarget == null) return; if (!basePosCached) { basePos = moveTarget.anchoredPosition; basePosCached = true; } } private void ResetToBase() { if (moveTarget != null && basePosCached) { if (!UI_OrderedEntryAnimator.IsLayoutSensitive(moveTarget)) moveTarget.anchoredPosition = basePos; } if (fadeTarget != null) { fadeTarget.alpha = 1f; fadeTarget.interactable = true; fadeTarget.blocksRaycasts = true; } } private void KillTween() { if (enterSequence != null) { enterSequence.Kill(); enterSequence = null; } if (moveTarget != null) moveTarget.DOKill(); if (fadeTarget != null) fadeTarget.DOKill(); } }