“虞渠成” 3a335e60a2 chore: 重构DOTween插件路径并更新相关代码
1. 将DOTween从原Plugins/DOTween迁移到Plugins/Demigiant/DOTween
2. 更新版本号解析逻辑,适配设备端压缩编码格式
3. 新增UI动画组件UIAnimator及其编辑器脚本
4. 优化主页设备列表项滑动菜单功能
5. 移除无用的VSCode编辑器包配置
6. 更新多语言文案修正末尾标点
7. 调整主页锁定超时配置为可配置项
2026-08-19 09:47:44 +08:00

158 lines
5.9 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System;
using System.Collections.Generic;
using DG.Tweening;
using UnityEngine;
/// <summary>
/// 可视化UI动画组件以步骤列表驱动DOTween播放
/// 支持 位移/缩放/旋转/透明度 四类动画,正向/反向/停止
/// 配合 UIAnimatorInspector 可在 Inspector 中可视化编排并预览
/// </summary>
public class UIAnimator : MonoBehaviour
{
public enum UIAnimationType
{
Move, // 位移(相对偏移)
Scale, // 缩放(目标值)
Rotate, // 旋转目标角度绕Z轴
Alpha // 透明度目标值需CanvasGroup
}
[Serializable]
public class UIAnimationStep
{
[Tooltip("动画类型")] public UIAnimationType type = UIAnimationType.Move;
[Tooltip("步骤开始前的延迟(秒)")] public float delay;
[Tooltip("动画时长(秒)")] public float duration = 0.5f;
[Tooltip("缓动曲线")] public Ease ease = Ease.OutQuad;
[Tooltip("位移偏移量(相对当前位置)")] public Vector3 moveOffset = Vector3.zero;
[Tooltip("缩放目标值")] public Vector3 targetScale = Vector3.one;
[Tooltip("旋转目标角度(绕Z轴)")] public float targetRotation;
[Tooltip("透明度目标值(0-1)")] public float targetAlpha = 1f;
}
[Tooltip("动画步骤列表")] public List<UIAnimationStep> steps = new List<UIAnimationStep>();
[Tooltip("启动时自动播放")] public bool playOnAwake;
[Tooltip("无CanvasGroup时自动添加(Alpha动画需要)")] public bool autoAddCanvasGroup = true;
private RectTransform rectTransform;
private CanvasGroup canvasGroup;
private Sequence sequence;
// 初始状态缓存(反向播放与编辑器预览需要)
public Vector3 InitialAnchoredPosition3D { get; private set; }
public Vector3 InitialLocalScale { get; private set; }
public float InitialRotationZ { get; private set; }
public float InitialAlpha { get; private set; }
public RectTransform RectTransform => rectTransform;
public CanvasGroup CanvasGroup => canvasGroup;
/// <summary>动画总时长(所有步骤的 延迟+时长 之和)</summary>
public float TotalDuration
{
get
{
float total = 0;
if (steps != null)
foreach (var step in steps) total += step.delay + step.duration;
return total;
}
}
private void Awake()
{
rectTransform = GetComponent<RectTransform>();
canvasGroup = GetComponent<CanvasGroup>();
if (canvasGroup == null && autoAddCanvasGroup)
canvasGroup = gameObject.AddComponent<CanvasGroup>();
SaveInitialState();
if (playOnAwake) Play();
}
/// <summary>记录当前状态为初始状态(反向播放/预览的基准)</summary>
public void SaveInitialState()
{
if (rectTransform == null) rectTransform = GetComponent<RectTransform>();
if (canvasGroup == null) canvasGroup = GetComponent<CanvasGroup>();
if (rectTransform == null) return;
InitialAnchoredPosition3D = rectTransform.anchoredPosition3D;
InitialLocalScale = rectTransform.localScale;
InitialRotationZ = rectTransform.localEulerAngles.z;
InitialAlpha = canvasGroup != null ? canvasGroup.alpha : 1f;
}
/// <summary>正向播放</summary>
public void Play() => PlaySequence(false);
/// <summary>反向播放(从当前状态回到初始状态)</summary>
public void PlayReverse() => PlaySequence(true);
/// <summary>停止并保持当前状态</summary>
public void Stop()
{
sequence?.Kill();
sequence = null;
}
private void PlaySequence(bool reverse)
{
sequence?.Kill();
sequence = reverse ? CreateReverseSequence() : CreateForwardSequence();
if (sequence == null) return;
sequence.Play();
}
private Sequence CreateForwardSequence()
{
if (rectTransform == null || steps == null || steps.Count == 0) return null;
Sequence seq = DOTween.Sequence();
foreach (var step in steps)
{
Tween t = CreateStepTween(step, false);
if (t == null) continue;
if (step.delay > 0) t.SetDelay(step.delay);
seq.Append(t);
}
return seq;
}
private Sequence CreateReverseSequence()
{
if (rectTransform == null || steps == null || steps.Count == 0) return null;
Sequence seq = DOTween.Sequence();
for (int i = steps.Count - 1; i >= 0; i--)
{
Tween t = CreateStepTween(steps[i], true);
if (t == null) continue;
if (steps[i].delay > 0) t.SetDelay(steps[i].delay);
seq.Append(t);
}
return seq;
}
private Tween CreateStepTween(UIAnimationStep step, bool reverse)
{
switch (step.type)
{
case UIAnimationType.Move:
// 反向时位移取负偏移(回到初始位置)
return rectTransform.DOAnchorPos3D(reverse ? -step.moveOffset : step.moveOffset, step.duration)
.SetRelative().SetEase(step.ease);
case UIAnimationType.Scale:
return rectTransform.DOScale(reverse ? InitialLocalScale : step.targetScale, step.duration).SetEase(step.ease);
case UIAnimationType.Rotate:
return rectTransform.DOLocalRotate(
new Vector3(0, 0, reverse ? InitialRotationZ : step.targetRotation), step.duration).SetEase(step.ease);
case UIAnimationType.Alpha:
if (canvasGroup == null)
{
Debug.LogWarning("[UIAnimator] Alpha动画需要CanvasGroup请手动添加或开启autoAddCanvasGroup", this);
return null;
}
return canvasGroup.DOFade(reverse ? InitialAlpha : step.targetAlpha, step.duration).SetEase(step.ease);
}
return null;
}
}