Unity使用dotween实现UI依次出现的动画效果之二

在这里插入图片描述在之前的基础上,新建了一个用OnEnable和OnDisable控制的脚本,添加了动态数字效果,可以在子物体上使用,实现大动画套小动画。
代码如下:

using UnityEngine;
using DG.Tweening; // 引入DoTween命名空间
using UnityEngine.UI; // 引入 UI 命名空间


public class UIAnimOnEnable : MonoBehaviour
{
    
    
    public GameObject[] uiElements; // 在Inspector中设置要依次弹出的UI元素
    public AnimationType[] animationTypes; // 为每个元素设置动画类型
    public float duration = 0.5f; // 动画持续时间
    public float delayBetweenElements = 0.2f; // 元素之间的延迟
    public float flyDistance = 500f; // 从底部飞入的距离

    // 保存原始位置和缩放状态
    private Vector3[] originalPositions;
    private Vector3[] originalScales;
    // 保存原始text文本数值
    public float originalfloat;

    public enum AnimationType // 定义动画类型
    {
    
    
        Pop,
        Fade,
        Bounce,
        FlyFromBottom,
        DynamicNumbers,
        No
    }

    void Awake()
    {
    
    
        InitializeUIElements();
    }
    private void OnEnable()
    {
    
    
        AnimateUIElements();
    }
    private void OnDisable()
    {
    
    
        AnimateUIElementsOut();
    }


    void InitializeUIElements()
    {
    
    
        // 检查数组长度是否匹配
        if (uiElements.Length == 0 || animationTypes.Length != uiElements.Length)
        {
    
    
            Debug.LogError("UI元素和动画类型数组长度不匹配!");
            return;
        }

        // 初始化原始位置和缩放数组
        originalPositions = new Vector3[uiElements.Length];
        originalScales = new Vector3[uiElements.Length];

        for (int i = 0; i < uiElements.Length; i++)
        {
    
    
            var element = uiElements[i];
            originalPositions[i] = element.transform.localPosition; // 保存原始位置
            originalScales[i] = element.transform.localScale; // 保存原始缩放

            // 检查并添加 CanvasGroup 组件
            CanvasGroup canvasGroup = element.GetComponent<CanvasGroup>();
            if (canvasGroup == null)
            {
    
    
                canvasGroup = element.AddComponent<CanvasGroup>();
            }
            // 初始化为透明并缩放为0,并且隐藏所有元素
            element.transform.localScale = Vector3.zero;
            canvasGroup.alpha = 0;
            element.SetActive(false); // 隐藏UI元素
        }
        Debug.Log("初始化");
    }

    void AnimateUIElements()
    {
    
    
        Debug.Log("播放入场动画");

        for (int i = 0; i < uiElements.Length; i++)
        {
    
    
            var element = uiElements[i];
            // 如果该元素已经激活并有动画在进行,跳出循环
            if (element.activeSelf) continue;

            // 停止该元素的所有动画
            element.transform.DOKill();
            CanvasGroup canvasGroup = element.GetComponent<CanvasGroup>();

            // 重置状态为透明并缩放为初始状态
            element.transform.localScale = Vector3.zero;
            canvasGroup.alpha = 0;

            // 激活UI元素
            element.SetActive(true);

            // 根据动画类型执行不同的动画
            AnimationType currentAnimation = animationTypes[i];

            switch (currentAnimation)
            {
    
    
               
                case AnimationType.Pop: // 弹出
                    element.transform.DOScale(originalScales[i], duration).SetDelay(i * delayBetweenElements);
                    canvasGroup.DOFade(1, duration).SetDelay(i * delayBetweenElements);
                    break;
                case AnimationType.Fade: // 淡入
                    element.transform.DOScale(originalScales[i], duration).SetDelay(i * delayBetweenElements);
                    canvasGroup.DOFade(1, duration).SetDelay(i * delayBetweenElements);
                    break;

                case AnimationType.Bounce: // 弹跳
                    element.transform.DOScale(originalScales[i], duration).SetEase(Ease.OutBounce).SetDelay(i * delayBetweenElements);
                    canvasGroup.DOFade(1, duration).SetDelay(i * delayBetweenElements);
                    break;

                case AnimationType.FlyFromBottom: // 从底部飞到原位置
                    element.transform.localPosition = originalPositions[i] + new Vector3(0, -flyDistance, 0); // 从初始化位置偏移
                    element.transform.DOLocalMove(originalPositions[i], duration).SetDelay(i * delayBetweenElements);
                    canvasGroup.DOFade(1, duration).SetDelay(i * delayBetweenElements);
                    element.transform.DOScale(originalScales[i], duration).SetDelay(i * delayBetweenElements);
                    break;
                case AnimationType.DynamicNumbers: // 动态数字效果
                    element.transform.localScale = originalScales[i];
                    canvasGroup.alpha = 1;
                    AnimateValue(element, duration*5); // 直接传递 duration
                    break;
                case AnimationType.No: // 无动效
                    element.SetActive(true);

                    break;
            }
        }
    }

    void AnimateUIElementsOut()
    {
    
    
        Debug.Log("播放退场动画");

        for (int i = 0; i < uiElements.Length; i++)
        {
    
    
            var element = uiElements[i];          

            // 停止该元素的所有动画
            element.transform.DOKill();
            CanvasGroup canvasGroup = element.GetComponent<CanvasGroup>();

            // 根据动画类型执行不同的退场动画
            AnimationType currentAnimation = animationTypes[i];
            // 定义一个动画完成后的逻辑
            Tween tween = null;
            switch (currentAnimation)
            {
    
    
                case AnimationType.Pop: // 弹出
                    tween = canvasGroup.DOFade(0, duration);
                    break;
                case AnimationType.Fade: // 淡出
                    tween = element.transform.DOScale(Vector3.zero, duration);
                    canvasGroup.DOFade(0, duration);
                    break;

                case AnimationType.Bounce: // 弹跳
                    tween = element.transform.DOScale(Vector3.zero, duration).SetEase(Ease.InBounce);
                    canvasGroup.DOFade(0, duration);
                    break;

                case AnimationType.FlyFromBottom: // 从底部飞出去
                    tween = element.transform.DOLocalMove(originalPositions[i] + new Vector3(0, -flyDistance, 0), duration);
                    canvasGroup.DOFade(0, duration);
                    element.transform.DOScale(Vector3.zero, duration);
                    break;
                case AnimationType.DynamicNumbers: // 动态数字效果
                    tween = canvasGroup.DOFade(0, duration);
                    element.transform.DOScale(Vector3.zero, duration);
                    break;
                case AnimationType.No: // 无动效
                    element.SetActive(false);

                    break;
            }

            // 在动画完成时禁用元素
            if (tween != null)
            {
    
    
                tween.OnComplete(() =>
                {
    
    
                    element.SetActive(false);
                });
            }
        }

    }


    private void AnimateValue(GameObject targetObject, float duration)
    {
    
    
        // 检查目标对象上是否有 Text 组件
        Text textComponent = targetObject.GetComponent<Text>();
        if (textComponent == null)
        {
    
    
            Debug.LogError("目标对象无 Text 组件");
            return;
        }       

        // 从 0 开始的动画
        float currentValue = 0;
        DOTween.To(() => currentValue, x =>
        {
    
    
            currentValue = x;
            textComponent.text = Mathf.Floor(currentValue).ToString(); // 更新文本显示
    }, originalfloat, duration);
    }
    private void OnApplicationQuit()
    {
    
    
        DOTween.KillAll(); // 在应用程序退出时停止所有 DOTween 动画
    }
}