当前位置: 首页 > news >正文

简单序列帧动画播放器,播放GIF

using UnityEngine;
using UnityEngine.UI;
using UnityEngine.U2D;

/// <summary>
/// 简单序列帧动画播放器
/// 支持直接拖入 SpriteAtlas 图集,自动提取并播放所有帧
/// </summary>
[RequireComponent(typeof(Image))]
public class SimpleSpriteAnimation : MonoBehaviour
{
[Header("图集(直接拖入)")]
[Tooltip("拖入 SpriteAtlas 图集,自动提取所有 Sprite")]
public SpriteAtlas atlas;

[Header("播放设置")]
[Tooltip("帧率(每秒播放帧数)")]
public float frameRate = 30f;

[Tooltip("是否自动播放")]
public bool playOnStart = true;

[Tooltip("是否循环播放")]
public bool loop = true;

// 提取的精灵帧
private Sprite[] frames;

// 当前帧索引
private int currentFrame = 0;

// 计时器
private float timer = 0f;

// 播放状态
private bool isPlaying = false;

// Image组件
private Image image;

/// <summary>
/// 总帧数
/// </summary>
public int FrameCount => frames?.Length ?? 0;

/// <summary>
/// 是否正在播放
/// </summary>
public bool IsPlaying => isPlaying;

private void Awake()
{
image = GetComponent<Image>();
}

private void Start()
{
ExtractFramesFromAtlas();

if (playOnStart && frames != null && frames.Length > 0)
{
Play();
}
}

private void Update()
{
if (!isPlaying || frames == null || frames.Length == 0)
return;

timer += Time.deltaTime;
float interval = 1f / frameRate;

while (timer >= interval)
{
timer -= interval;
NextFrame();
}
}

/// <summary>
/// 从 SpriteAtlas 提取所有帧
/// </summary>
private void ExtractFramesFromAtlas()
{
if (atlas == null)
return;

// 获取图集中的 Sprite 数量
int spriteCount = atlas.spriteCount;
frames = new Sprite[spriteCount];

// 提取所有 Sprite
Sprite[] tempSprites = new Sprite[spriteCount];
atlas.GetSprites(tempSprites);

// 按名称数字排序
System.Array.Sort(tempSprites, (a, b) =>
{
int numA = ExtractNumber(a.name);
int numB = ExtractNumber(b.name);
return numA.CompareTo(numB);
});

frames = tempSprites;
}

/// <summary>
/// 从 Sprite 名称中提取数字用于排序
/// </summary>
private int ExtractNumber(string name)
{
// 移除 "(Clone)" 后缀(GetSprites 会添加)
name = name.Replace("(Clone)", "");

int number;
if (int.TryParse(name, out number))
return number;

// 尝试提取数字部分
for (int i = 0; i < name.Length; i++)
{
if (char.IsDigit(name[i]))
{
int start = i;
while (i < name.Length && char.IsDigit(name[i]))
i++;
if (int.TryParse(name.Substring(start, i - start), out number))
return number;
}
}

return int.MaxValue;
}

/// <summary>
/// 播放动画
/// </summary>
public void Play()
{
if (frames == null || frames.Length == 0)
{
ExtractFramesFromAtlas();
}

if (frames == null || frames.Length == 0)
return;

isPlaying = true;
timer = 0f;
UpdateFrame();
}

/// <summary>
/// 暂停动画
/// </summary>
public void Pause()
{
isPlaying = false;
}

/// <summary>
/// 停止动画(暂停并重置到第一帧)
/// </summary>
public void Stop()
{
isPlaying = false;
currentFrame = 0;
timer = 0f;
UpdateFrame();
}

/// <summary>
/// 重新播放
/// </summary>
public void Replay()
{
currentFrame = 0;
timer = 0f;
Play();
}

/// <summary>
/// 跳转到下一帧
/// </summary>
private void NextFrame()
{
currentFrame++;

if (currentFrame >= frames.Length)
{
if (loop)
{
currentFrame = 0;
}
else
{
currentFrame = frames.Length - 1;
isPlaying = false;
return;
}
}

UpdateFrame();
}

/// <summary>
/// 更新显示的帧
/// </summary>
private void UpdateFrame()
{
if (frames != null && frames.Length > 0 && image != null)
{
image.sprite = frames[currentFrame];
}
}
}

Resource下文件

http://www.jsqmd.com/news/805331/

相关文章:

  • 【python】离线安装库到内网中
  • 开源AI代码生成工具unsaged:本地化部署与高效开发实践
  • vsftpd匿名用户本地用户虚拟用户总结【20260512】001篇
  • 淘宝要接入AI购物助手:以后买东西,可能不是搜索,而是“让AI帮你挑”
  • Midjourney Sumi-e风格合规性预警:2024Q3版权新规下,3类易侵权水墨元素识别清单与安全替代方案(含JIS X 9051标准对照)
  • 终极PS4存档管理指南:Apollo Save Tool完全解析
  • 个人开发者如何利用Taotoken模型广场快速选型并验证创意原型
  • 2026届必备的五大AI辅助写作助手解析与推荐
  • 百元级GEO工具真的能生成高质量内容吗?
  • 终极VLC美化指南:5款VeLoCity专业主题让你的播放器焕然一新
  • 忆阻器争议:从数学定义到产业应用,如何理解下一代存储技术
  • 35岁零基础转行网络安全?值得吗?
  • 怎么解决梨采摘后的果肉黑心问题
  • 基于Dlib与OpenCV的人脸关键点检测实战:从静态图片到实时视频
  • 基于STM32CubeMX与HAL库的MAX30102心率血氧监测系统实战指南
  • 穿透 MQ 专栏 (五):【终局之战】MySQL 和 MQ 的世纪联姻:扒开“分布式事务”的遮羞布
  • 工程师远程高效设计:从工具链到协作心法的实战指南
  • 35岁裸辞转行网络安全!零基础入门的真实励志案例,建议收藏
  • 要以战养兵,不要纸上谈兵
  • 电子仪器CE标志合规:从技术文件到尽职调查的完整指南
  • 别再用暴力搜索了!用C++解鸡兔同笼,这几种算法思路让你面试加分
  • 你的音乐被“囚禁“了?ncmdumpGUI终极解锁指南:让NCM文件重获自由
  • 终极指南:如何在Windows上轻松安装安卓APK应用
  • 别再手动调参了!用Matlab Regression Learner App,5分钟搞定你的第一个回归模型
  • 别瞎转了!零基础拿捏网络安全,看这篇“保姆级”避坑指南就够了
  • Taotoken用量看板如何帮助团队清晰管理大模型支出
  • 慕尼黑电子展:洞察汽车电子、工业物联网与功率半导体技术趋势
  • 高效轻量级:APK Installer带你告别臃肿模拟器,在Windows上无缝安装安卓应用
  • 在Cursor中配置MCP Server
  • 暗黑破坏神2存档编辑器完整指南:轻松打造完美角色