DCS/ruiyiweiUX/Assets/GeneralTools/Scripts/Always/Frames/FrameAnimator.cs

174 lines
4.9 KiB
C#
Raw Normal View History

2026-06-09 13:59:11 +08:00
using UnityEngine;
using UnityEngine.UI;
using System;
using System.Collections.Generic;
using System.IO;
namespace GeneralTools
{
/// <summary>
/// 序列帧动画播放器
/// 支持UGUI的Image和Unity2D的SpriteRenderer
/// </summary>
public class FrameAnimator : MonoBehaviour
{
//目标Image组件
private RawImage image;
/// <summary>
/// 序列帧
/// </summary>
private List<Texture> frames = null;
/// <summary>
/// 帧率
/// </summary>
private float framerate = 24.0f;
/// <summary>
/// 是否忽略timeScale
/// </summary>
private bool ignoreTimeScale = true;
/// <summary>
/// 是否循环
/// </summary>
private bool loop = true;
/// <summary>
/// 是否允许播放
/// </summary>
private bool isAllowPlay = false;
/// <summary>
/// 结束事件
/// 在每次播放完一个周期时触发
/// 在循环模式下触发此事件时,当前帧不一定为结束帧
/// </summary>
public event Action OnFinishEvent;
//当前帧索引
private int currentFrameIndex = 0;
//下一次更新时间
private float timer = 0.0f;
public FrameAnimator Init(List<Texture> _frames, bool _loop, float _framerate = 24)
{
Stop();
image = GetComponent<RawImage>();
if (image == null)
{
Debug.LogError("未找到RawImage", gameObject);
}
frames = _frames;
loop = _loop;
framerate = _framerate;
image.texture = _frames[0];
OnFinishEvent = null;
return this;
}
public void Play()
{
isAllowPlay = true;
gameObject.SetActive(true);
}
public void Pause()
{
isAllowPlay = false;
}
public void Stop()
{
isAllowPlay = false;
ResetIndex();
}
public void Hide()
{
Stop();
gameObject.SetActive(false);
}
public void RePlay()
{
isAllowPlay = false;
ResetIndex();
if (frames.Count > 0)
{
image.texture = frames[currentFrameIndex];
}
Play();
}
public void SetLoop(bool _loop)
{
loop = _loop;
}
/// <summary>
/// 重设动画索引
/// </summary>
private int ResetIndex()
{
currentFrameIndex = framerate > 0 ? 0 : frames.Count - 1;
return currentFrameIndex;
}
void FixedUpdate()
{
//帧数据无效,禁用脚本
if (frames == null || frames.Count == 0 || image == null || frames.Count == 1 || framerate == 0)
{
return;
}
else
{
//是否允许播放
if (!isAllowPlay) return;
//获取当前时间
float time = ignoreTimeScale ? Time.unscaledTime : Time.time;
//计算帧间隔时间
float interval = Mathf.Abs(1.0f / framerate);
//满足更新条件,执行更新操作
if (time - timer > interval)
{
//执行更新操作
DoUpdate();
}
}
}
//具体更新操作
private void DoUpdate()
{
//计算新的索引
int nextIndex = currentFrameIndex + (framerate > 0 ? 1 : -1);
//索引越界,表示已经到结束帧
if (nextIndex < 0 || nextIndex >= frames.Count)
{
//非循环,模式结束
if (loop == false)
{
isAllowPlay = false;
//播放结束事件
OnFinishEvent?.Invoke();
nextIndex = frames.Count - 1;
}
else
{
nextIndex = ResetIndex();
}
}
//钳制索引
currentFrameIndex = Mathf.Clamp(nextIndex, 0, frames.Count - 1);
//更新图片
RefreshTexture(currentFrameIndex);
//设置计时器为当前时间
timer = ignoreTimeScale ? Time.unscaledTime : Time.time;
}
private void RefreshTexture(int index)
{
image.texture = frames[index];
}
//正向手动刷新
public void ManualUpdatePositive()
{
DoUpdate();
}
//反向手动刷新
public void ManualUpdateReverse()
{
framerate *= -1;
DoUpdate();
framerate *= -1;
}
}
}