This commit is contained in:
SoulliesOfficial
2025-08-22 14:54:40 -04:00
parent 6aa498f6be
commit 70b2a43824
574 changed files with 173713 additions and 1884 deletions

View File

@@ -0,0 +1,122 @@
using System.Collections;
using System.Collections.Generic;
using DG.Tweening;
using TMPro;
using UnityEngine;
namespace Ichni.UI
{
public class TextCatapult : MonoBehaviour
{
[Header("UI 元素")] [Tooltip("第一个文本组件")] [SerializeField]
private TMP_Text textA;
[Tooltip("第二个文本组件")] [SerializeField] private TMP_Text textB;
[Header("动画参数")] [Tooltip("文本在中央停留显示的时间")] [SerializeField]
private float displayDuration = 4f;
[Tooltip("向上移动和淡入淡出的动画时间")] [SerializeField]
private float animationDuration = 1f;
[Tooltip("文本向上移动的距离")] [SerializeField]
private float moveDistance = 200f;
// --- 可选: 如果你想让文字内容循环变化 ---
[Header("可选的文本内容")] [Tooltip("在这里填入你想循环显示的文字列表")] [SerializeField]
private List<string> textContents = new List<string>();
private TMP_Text[] _textElements;
private int _currentTextIndex = 0; // 当前显示在中央的文本的索引 (0 或 1)
private int _contentIndex = 0; // 当前显示内容的索引
private Vector2 _centerPosition;
private Sequence _animationSequence;
void Start()
{
Setup();
// 直接启动第一个动画过渡
AnimateTransition();
}
void OnDestroy()
{
// 安全地杀死所有相关的DoTween动画防止在场景切换或对象销毁时出错
_animationSequence?.Kill();
}
/// <summary>
/// 初始化设置
/// </summary>
private void Setup()
{
_textElements = new[] { textA, textB };
// 记录中心位置
_centerPosition = textA.rectTransform.anchoredPosition;
// 设置 textA 的初始状态
textA.rectTransform.anchoredPosition = _centerPosition;
textA.alpha = 1f;
UpdateTextContent(textA); // 设置初始文字
// 设置 textB 的初始状态 (在下方,透明)
textB.rectTransform.anchoredPosition = _centerPosition - new Vector2(0, moveDistance);
textB.alpha = 0f;
// textB 的内容将在它动画开始前更新,所以这里无需设置
}
/// <summary>
/// 执行一次完整的文本过渡动画,并在完成后自我调用以形成循环
/// </summary>
private void AnimateTransition()
{
// 确定哪个文本要移出,哪个要移入
TMP_Text textToAnimateOut = _textElements[_currentTextIndex];
TMP_Text textToAnimateIn = _textElements[(_currentTextIndex + 1) % 2];
// 创建一个新的动画序列
_animationSequence = DOTween.Sequence();
_animationSequence
.AppendInterval(displayDuration) // 1. 等待当前文本显示4秒
.AppendCallback(() => {
// 2. 在动画开始前,更新即将进入的文本的内容
UpdateTextContent(textToAnimateIn);
})
// 3. 同时执行两个文本的动画
.Append(textToAnimateOut.rectTransform.DOAnchorPosY(_centerPosition.y + moveDistance, animationDuration).SetEase(Ease.OutCubic))
.Join(textToAnimateOut.DOFade(0f, animationDuration).SetEase(Ease.OutCubic))
.Join(textToAnimateIn.rectTransform.DOAnchorPosY(_centerPosition.y, animationDuration).SetEase(Ease.OutCubic))
.Join(textToAnimateIn.DOFade(1f, animationDuration).SetEase(Ease.OutCubic))
.OnComplete(() => {
// 4. 当整个过渡动画完成时
// 将刚刚移出的文本复位到起始位置,为下一次进入做准备
textToAnimateOut.rectTransform.anchoredPosition = _centerPosition - new Vector2(0, moveDistance);
// 切换当前文本的索引,为下个循环做准备
_currentTextIndex = (_currentTextIndex + 1) % 2;
// 启动下一次动画过渡,形成循环
AnimateTransition();
});
_animationSequence.Play();
}
/// <summary>
/// 更新文本内容(如果列表不为空)
/// </summary>
private void UpdateTextContent(TMP_Text textElement)
{
if (textContents == null || textContents.Count == 0)
{
return; // 如果列表为空,则不改变文字
}
textElement.text = textContents[_contentIndex];
_contentIndex = (_contentIndex + 1) % textContents.Count; // 移动到下一个内容索引,并循环
}
}
}