给UI界面加点入场动效,退场就直接倒放。
预设了四种效果,弹出、淡入、弹跳、从底部飞到原位置,用枚举定义动画类型方便切换效果。
挂载到场景物体上:
效果如下:
屏幕录制 2024-10-24 100120
代码如下:
using UnityEngine;
using DG.Tweening; // 引入DoTween命名空间
public class UIAnimator : 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;
public enum AnimationType // 定义动画类型
{
Pop,
Fade,
Bounce,
FlyFromBottom
}
void Start()
{
InitializeUIElements();
}
void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
AnimateUIElements();//入场
}
else if (Input.GetKeyDown(KeyCode.Return))
{
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元素
}
}
void AnimateUIElements()
{
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;
}
}
}
void AnimateUIElementsOut()
{
for (int i = 0; i < uiElements.Length; i++)
{
var element = uiElements[i];
// 如果该元素没有激活,则跳过
if (!element.activeSelf) continue;
// 停止该元素的所有动画
element.transform.DOKill();
CanvasGroup canvasGroup = element.GetComponent<CanvasGroup>();
// 根据动画类型执行不同的退场动画
AnimationType currentAnimation = animationTypes[i];
switch (currentAnimation)
{
case AnimationType.Pop: // 弹出
case AnimationType.Fade: // 淡出
element.transform.DOScale(Vector3.zero, duration);
canvasGroup.DOFade(0, duration);
break;
case AnimationType.Bounce: // 弹跳
element.transform.DOScale(Vector3.zero, duration).SetEase(Ease.InBounce);
canvasGroup.DOFade(0, duration);
break;
case AnimationType.FlyFromBottom: // 从底部飞出去
element.transform.DOLocalMove(originalPositions[i] + new Vector3(0, -flyDistance, 0), duration);
canvasGroup.DOFade(0, duration);
element.transform.DOScale(Vector3.zero, duration);
break;
}
// 动画完成后禁用元素
StartCoroutine(DisableElementAfterAnimation(element, duration));
}
}
private System.Collections.IEnumerator DisableElementAfterAnimation(GameObject element, float waitTime)
{
yield return new WaitForSeconds(waitTime);
element.SetActive(false);
}
}