251 lines
7.9 KiB
C#
251 lines
7.9 KiB
C#
|
using System.Collections;
|
|||
|
using System.Collections.Generic;
|
|||
|
using System.Linq;
|
|||
|
using UnityEngine;
|
|||
|
using DG.Tweening;
|
|||
|
using UnityEngine.UI;
|
|||
|
|
|||
|
// 定义一个具体的基类,所有UI动画效果继承自这个类
|
|||
|
[System.Serializable]
|
|||
|
public class BaseUIEffect
|
|||
|
{
|
|||
|
public int ListIndex; // 用于排序的索引
|
|||
|
public virtual Tweener ApplyUIAnimation(RectTransform target, CanvasGroup canvasGroup)
|
|||
|
{
|
|||
|
// 在基类中实现一个默认的动画行为
|
|||
|
Debug.Log("基类UI动画未实现");
|
|||
|
return null;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// 定义UI动画效果类,继承自 BaseUIEffect
|
|||
|
[System.Serializable]
|
|||
|
public class UIAnimationEffect : BaseUIEffect
|
|||
|
{
|
|||
|
public enum AnimationType { Move, Rotate, Scale, Fade } // 动画类型
|
|||
|
public AnimationType animationType; // 当前动画类型
|
|||
|
|
|||
|
public Vector3 targetValue; // 目标值(位移、旋转或缩放)
|
|||
|
public float duration = 1f; // 动画持续时间
|
|||
|
public Ease easeType = Ease.Linear; // 缓动类型
|
|||
|
public float targetAlpha; // 用于透明度动画
|
|||
|
|
|||
|
// 重写 ApplyUIAnimation 方法
|
|||
|
public override Tweener ApplyUIAnimation(RectTransform target, CanvasGroup canvasGroup)
|
|||
|
{
|
|||
|
Tweener tweener = null;
|
|||
|
|
|||
|
switch (animationType)
|
|||
|
{
|
|||
|
case AnimationType.Move:
|
|||
|
tweener = target.DOAnchorPos(targetValue, duration).SetEase(easeType);
|
|||
|
break;
|
|||
|
case AnimationType.Rotate:
|
|||
|
tweener = target.DORotate(targetValue, duration).SetEase(easeType);
|
|||
|
break;
|
|||
|
case AnimationType.Scale:
|
|||
|
tweener = target.DOScale(targetValue, duration).SetEase(easeType);
|
|||
|
break;
|
|||
|
case AnimationType.Fade:
|
|||
|
if (canvasGroup != null)
|
|||
|
{
|
|||
|
tweener = canvasGroup.DOFade(targetAlpha, duration).SetEase(easeType);
|
|||
|
}
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
return tweener;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// 定义抖动效果类,继承自 BaseUIEffect
|
|||
|
[System.Serializable]
|
|||
|
public class UIShakeEffect : BaseUIEffect
|
|||
|
{
|
|||
|
public enum ShakeType { Position, Rotation } // 抖动类型
|
|||
|
public ShakeType shakeType; // 当前抖动类型
|
|||
|
|
|||
|
public Vector3 strength = Vector3.one; // 抖动强度
|
|||
|
public int vibrato = 10; // 抖动次数
|
|||
|
public float randomness = 90f; // 抖动的随机性
|
|||
|
public float duration = 1f; // 抖动持续时间
|
|||
|
|
|||
|
// 重写 ApplyUIAnimation 方法,处理UI抖动效果
|
|||
|
public override Tweener ApplyUIAnimation(RectTransform target, CanvasGroup canvasGroup)
|
|||
|
{
|
|||
|
Tweener tweener = null;
|
|||
|
|
|||
|
switch (shakeType)
|
|||
|
{
|
|||
|
case ShakeType.Position:
|
|||
|
tweener = target.DOShakeAnchorPos(duration, strength, vibrato, randomness);
|
|||
|
break;
|
|||
|
case ShakeType.Rotation:
|
|||
|
tweener = target.DOShakeRotation(duration, strength, vibrato, randomness);
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
return tweener;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public class AnimationUI : MonoBehaviour
|
|||
|
{
|
|||
|
public Button button;//UI按钮
|
|||
|
public RectTransform targetRectTransform; // UI目标对象的RectTransform
|
|||
|
public CanvasGroup targetCanvasGroup; // UI透明度控制的CanvasGroup
|
|||
|
|
|||
|
public List<UIAnimationEffect> uiAnimationEffects = new List<UIAnimationEffect>(); // 存储UI动画效果
|
|||
|
public List<UIShakeEffect> uiShakeEffects = new List<UIShakeEffect>(); // 存储UI抖动效果
|
|||
|
public bool loopEntireSequence = false; // 是否循环整个动画序列
|
|||
|
public LoopType sequenceLoopType = LoopType.Restart; // 整个序列的循环类型
|
|||
|
|
|||
|
// 动画序列缓存
|
|||
|
private Sequence cachedAnimationSequence;
|
|||
|
|
|||
|
// 追踪动画列表是否需要更新
|
|||
|
[HideInInspector]
|
|||
|
public bool animationSequenceNeedsUpdate = true;
|
|||
|
|
|||
|
public int OnenableOpen;//是否一唤醒就动画
|
|||
|
|
|||
|
private void Awake()
|
|||
|
{
|
|||
|
DOTween.Init();
|
|||
|
targetRectTransform = GetComponent<RectTransform>();
|
|||
|
}
|
|||
|
private void OnEnable()
|
|||
|
{
|
|||
|
if (OnenableOpen == 0)
|
|||
|
{
|
|||
|
PlayUIAnimations();
|
|||
|
}
|
|||
|
else if (OnenableOpen == 1)
|
|||
|
{
|
|||
|
|
|||
|
if (button == null)
|
|||
|
{
|
|||
|
if (!TryGetComponent<Button>(out button))
|
|||
|
{
|
|||
|
Debug.LogWarning("未添加组件按钮");
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
button.onClick.AddListener(PlayUIAnimations);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
else if (OnenableOpen == 2)
|
|||
|
{
|
|||
|
RestartAnimations();
|
|||
|
}
|
|||
|
}
|
|||
|
private void OnDisable()
|
|||
|
{
|
|||
|
if (OnenableOpen == 2)
|
|||
|
{
|
|||
|
gameObject.SetActive(true);
|
|||
|
cachedAnimationSequence.OnComplete(() =>
|
|||
|
{
|
|||
|
gameObject.SetActive(false);
|
|||
|
});
|
|||
|
PlayUIAnimations();
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
RestartAnimations();
|
|||
|
}
|
|||
|
}
|
|||
|
// 更新动画序列,当动画效果更改时调用此方法
|
|||
|
public void UpdateUIAnimationSequence()
|
|||
|
{
|
|||
|
// 如果已经有缓存的动画序列,先停止并销毁
|
|||
|
if (cachedAnimationSequence != null)
|
|||
|
{
|
|||
|
cachedAnimationSequence.Kill();
|
|||
|
}
|
|||
|
// 创建新的动画序列
|
|||
|
cachedAnimationSequence = DOTween.Sequence().SetAutoKill(false); ;
|
|||
|
|
|||
|
// 将两个列表合并并按 ListIndex 排序
|
|||
|
List<BaseUIEffect> sortedEffects = new List<BaseUIEffect>();
|
|||
|
sortedEffects.AddRange(uiAnimationEffects);
|
|||
|
sortedEffects.AddRange(uiShakeEffects);
|
|||
|
|
|||
|
// 按 ListIndex 排序
|
|||
|
sortedEffects = sortedEffects.OrderBy(effect => effect.ListIndex).ToList();
|
|||
|
|
|||
|
// 遍历排序后的效果列表,按顺序生成动画
|
|||
|
// 遍历排序后的效果列表,按顺序生成动画
|
|||
|
foreach (var effect in sortedEffects)
|
|||
|
{
|
|||
|
if (effect is UIAnimationEffect uiAnimationEffect)
|
|||
|
{
|
|||
|
// 移除这一行,避免强制将所有动画类型变成 Fade
|
|||
|
// uiAnimationEffect.animationType = UIAnimationEffect.AnimationType.Fade;
|
|||
|
|
|||
|
// 检查 CanvasGroup 是否存在(只针对 Fade 动画类型)
|
|||
|
if (uiAnimationEffect.animationType == UIAnimationEffect.AnimationType.Fade && !TryGetComponent<CanvasGroup>(out targetCanvasGroup))
|
|||
|
{
|
|||
|
Debug.LogWarning("没有添加组件CanvasGroup");
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// 应用动画
|
|||
|
Tweener tweener = effect.ApplyUIAnimation(targetRectTransform, targetCanvasGroup);
|
|||
|
if (tweener != null)
|
|||
|
{
|
|||
|
cachedAnimationSequence.Append(tweener);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
// 如果需要让整个序列循环
|
|||
|
if (loopEntireSequence)
|
|||
|
{
|
|||
|
cachedAnimationSequence.SetLoops(-1, sequenceLoopType);
|
|||
|
}
|
|||
|
|
|||
|
// 标记动画序列已经更新
|
|||
|
animationSequenceNeedsUpdate = false;
|
|||
|
}
|
|||
|
|
|||
|
// 播放动画,如果动画序列需要更新则先更新
|
|||
|
public void PlayUIAnimations()
|
|||
|
{
|
|||
|
if (animationSequenceNeedsUpdate)
|
|||
|
{
|
|||
|
UpdateUIAnimationSequence();
|
|||
|
}
|
|||
|
|
|||
|
if (cachedAnimationSequence != null)
|
|||
|
{
|
|||
|
cachedAnimationSequence.Play();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// 停止动画
|
|||
|
public void StopUIAnimations()
|
|||
|
{
|
|||
|
if (cachedAnimationSequence != null)
|
|||
|
{
|
|||
|
cachedAnimationSequence.Kill();
|
|||
|
animationSequenceNeedsUpdate = true;
|
|||
|
}
|
|||
|
}
|
|||
|
//复位
|
|||
|
public void RestartAnimations()
|
|||
|
{
|
|||
|
if (cachedAnimationSequence != null)
|
|||
|
{
|
|||
|
cachedAnimationSequence.Restart();
|
|||
|
cachedAnimationSequence.Pause();
|
|||
|
}
|
|||
|
}
|
|||
|
// 当Inspector面板中的值发生更改时调用
|
|||
|
private void OnValidate()
|
|||
|
{
|
|||
|
// Debug.Log("UI动画更新");
|
|||
|
animationSequenceNeedsUpdate = true;
|
|||
|
}
|
|||
|
}
|