151 lines
6.1 KiB
C#
151 lines
6.1 KiB
C#
![]() |
using Base;
|
|||
|
using TMPro;
|
|||
|
using UnityEngine;
|
|||
|
|
|||
|
namespace Prefab
|
|||
|
{
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 临时动画文本组件,用于在指定时间内逐帧显示一系列文本动画。
|
|||
|
/// 该组件假设 TemporaryAnimator 实现了 ITickable 接口,因此可以在游戏循环中接收更新。
|
|||
|
/// </summary>
|
|||
|
public class TemporaryAnimatorText : TemporaryAnimator
|
|||
|
{
|
|||
|
/// <summary>
|
|||
|
/// 用于显示动画文本的 TMP_Text 组件。
|
|||
|
/// 允许在编辑器中赋值,以增加灵活性和鲁棒性。
|
|||
|
/// </summary>
|
|||
|
[SerializeField] public TMP_Text text;
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 当前播放的动画帧索引。
|
|||
|
/// </summary>
|
|||
|
private int currentFrameIndex = 0;
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 存储所有动画帧文本的字符串数组。每个元素代表一帧动画内容。
|
|||
|
/// </summary>
|
|||
|
private string[] animationsKey;
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 每帧动画的持续时间(秒)。根据帧率(FPS)计算得出。
|
|||
|
/// </summary>
|
|||
|
private float frameDuration;
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 用于跟踪当前帧已持续时间的计时器。
|
|||
|
/// </summary>
|
|||
|
private float timer;
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 初始化动画文本组件。
|
|||
|
/// </summary>
|
|||
|
/// <param name="s">包含所有动画帧文本的字符串,多个帧之间用逗号分隔。</param>
|
|||
|
/// <param name="fps">动画播放的帧率(Frames Per Second)。</param>
|
|||
|
public void Init(string s, float fps=3)
|
|||
|
{
|
|||
|
// 如果文本组件未赋值,尝试在子对象中查找。
|
|||
|
// 如果仍未找到,则记录错误并提前退出。
|
|||
|
if (!text)
|
|||
|
{
|
|||
|
text = GetComponentInChildren<TMP_Text>();
|
|||
|
if (!text)
|
|||
|
{
|
|||
|
Debug.LogError("TemporaryAnimatorText: 未在子对象中找到或未指定 TMP_Text 组件。动画无法进行。", this);
|
|||
|
|
|||
|
return; // 提前退出 Init 方法,避免后续操作使用未初始化的 text
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// 处理输入字符串为 null 或空字符串的情况。
|
|||
|
// 在这种情况下,动画将显示空字符串或停止。
|
|||
|
if (string.IsNullOrEmpty(s))
|
|||
|
{
|
|||
|
Debug.LogWarning("TemporaryAnimatorText: 输入的动画字符串为空或为 null。动画将显示空字符串或停止。", this);
|
|||
|
animationsKey = new string[] { "" }; // 确保 animationsKey 不为 null 且至少包含一个空字符串元素
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
animationsKey = s.Split(',');
|
|||
|
// 如果 s.Split(',') 结果为空数组(这种情况极少见,但在某些 Split 重载下可能发生),也应进行处理。
|
|||
|
if (animationsKey.Length == 0)
|
|||
|
{
|
|||
|
Debug.LogWarning("TemporaryAnimatorText: 输入的动画字符串导致动画帧数组为空。动画将显示空字符串或停止。", this);
|
|||
|
animationsKey = new string[] { "" };
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// 检查帧率(FPS)的合法性。FPS 必须是大于 0 的正值。
|
|||
|
// 如果帧率不合法,则设置为默认值,防止除以零或动画速度异常。
|
|||
|
if (fps <= 0)
|
|||
|
{
|
|||
|
Debug.LogError("TemporaryAnimatorText: FPS 必须是大于 0 的正值。将动画帧持续时间设置为 1 秒。", this);
|
|||
|
this.frameDuration = 1f; // 默认每帧1秒,实际效果是动画暂停或非常慢
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
this.frameDuration = 1f / fps;
|
|||
|
}
|
|||
|
|
|||
|
// 重新初始化动画时,将当前帧索引重置为第一帧。
|
|||
|
currentFrameIndex = 0;
|
|||
|
|
|||
|
// 在 animationsKey 准备好后,设置初始文本为第一帧的内容。
|
|||
|
if (text && animationsKey.Length > 0)
|
|||
|
{
|
|||
|
text.text = animationsKey[currentFrameIndex];
|
|||
|
}
|
|||
|
// 如果动画帧数组为空,但文本组件存在,则清空文本显示。
|
|||
|
else if (text)
|
|||
|
{
|
|||
|
text.text = "";
|
|||
|
}
|
|||
|
|
|||
|
// 重置计时器,从零开始计算新帧的持续时间。
|
|||
|
timer = 0f;
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 每帧更新动画显示。该方法将在游戏循环中被 Clock 调用。
|
|||
|
/// </summary>
|
|||
|
public override void Tick()
|
|||
|
{
|
|||
|
base.Tick();
|
|||
|
if (!text)
|
|||
|
{
|
|||
|
Debug.LogWarning("TemporaryAnimatorText: 在 Tick 方法执行期间 TMP_Text 组件为 null。正在从 Clock 中移除。", this);
|
|||
|
return; // 无法执行动画,直接返回
|
|||
|
}
|
|||
|
|
|||
|
// 检查动画帧数组是否已初始化或为空。
|
|||
|
// 如果没有动画帧,则无需更新,直接返回。
|
|||
|
if (animationsKey == null || animationsKey.Length == 0)
|
|||
|
{
|
|||
|
// Debug.LogWarning("TemporaryAnimatorText: 动画键未初始化或为空。跳过 Tick 更新。", this); // 这条日志已被注释掉,避免频繁输出不必要的警告
|
|||
|
return; // 没有动画帧,直接返回
|
|||
|
}
|
|||
|
|
|||
|
// 增加计时器。
|
|||
|
timer += Time.deltaTime;
|
|||
|
|
|||
|
// 如果当前帧的持续时间已达到或超过预设的帧持续时间,则更新到下一帧。
|
|||
|
if (!(timer >= frameDuration)) return;
|
|||
|
|
|||
|
// 减去一帧的持续时间,以便计算下一帧的剩余时间,或者处理帧率不精确导致的累计误差。
|
|||
|
timer -= frameDuration;
|
|||
|
|
|||
|
// 移动到下一帧。
|
|||
|
currentFrameIndex += 1;
|
|||
|
|
|||
|
// 如果当前帧索引超出动画帧数组的范围,则循环回到第一帧。
|
|||
|
if (currentFrameIndex >= animationsKey.Length)
|
|||
|
{
|
|||
|
currentFrameIndex = 0;
|
|||
|
}
|
|||
|
|
|||
|
// 更新文本组件显示为当前帧的文本内容。
|
|||
|
text.text = animationsKey[currentFrameIndex];
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
}
|