using UnityEngine;
using UnityEngine.UI;
using System.Collections;
using System.IO;
public class SequenceFrameAnimation : MonoBehaviour
{
public static SequenceFrameAnimation instance;
#region Attributes
//[SerializeField]
RawImage mUnitySprite;
[Header("当前帧图片"), SerializeField]
Texture texture;
[Header("序列帧路径,Resources 文件加下")]
public string m_Path;
[Header("最大循环帧数"), Range(0, 2500)]
public int framesMax =202;
[Header("当前帧数")]
public int frameIndex = 0;
[Header("帧率"), SerializeField]
protected float framerate = 30;
[Header("忽略时间缩放,影响序列帧播放速度")]
bool ignoreTimeScale = true;
[Header("是否循环")]
public bool loop = false;
[Header("是否播放")]
public bool isPlay = false;
float mUpdate = 0f;
//CanvasGroup canvasGroup;
/// <summary>
/// Returns is the animation is still playing or not
/// </summary>
public bool isPlaying { get { return enabled; } }
/// <summary>
/// Animation framerate.
/// </summary>
public float framesPerSecond { get { return framerate; } set { framerate = value; } }
/// <summary>
/// Real time since startup.
/// </summary>
static public float realtime { get { return Time.unscaledTime; } }
public delegate void EndHandler();//声明委托
public event EndHandler EndEvent; //声明事件
#endregion
#region Unity3d Function
private void Awake()
{
if (!instance)
{
instance = this;
}
}
void Start()
{
mUnitySprite = GetComponent<RawImage>();
//if (mUnitySprite)
//{
// canvasGroup = mUnitySprite.gameObject.AddComponent<CanvasGroup>();
// canvasGroup.alpha = 0;
//}
//GameObject.Find("Play").GetComponent<Button>().onClick.AddListener(delegate () {
// Play();
//});
//GameObject.Find("Pause").GetComponent<Button>().onClick.AddListener(delegate () {
// Pause();
//});
//GameObject.Find("PlayBack").GetComponent<Button>().onClick.AddListener(delegate () {
// PlayBack();
// isBack = true;
//});
}
void Update()
{
UpdateRun();
}
#endregion
#region Public Function
/// <summary>
/// 设置序列帧路径
/// </summary>
/// <param name="path"></param>
public void SetFilePath(string path)
{
if (!string.IsNullOrEmpty(path))
{
m_Path = path;
string filePath = Application.dataPath + "/Resources/" + m_Path;
filePath = filePath.Replace("//", "\\");
string[] files = Directory.GetFiles(@filePath, "*.png");
framesMax = files.Length;
}
}
/// <summary>
/// 播放
/// </summary>
public void Play()
{
if (framesMax > 0)
{
if (!enabled && !loop)
{
int newIndex = framerate > 0 ? frameIndex + 1 : frameIndex - 1;
if (newIndex < 0 || newIndex >= framesMax)
{
frameIndex = framerate < 0 ? framesMax - 1 : 0;
}
}
enabled = isPlay = true;
UpdateSprite();
}
}
/// <summary>
/// 倒播
/// </summary>
public void PlayBack()
{
if (framesMax > 0)
{
if (!enabled && !loop)
{
int newIndex = framerate > 0 ? frameIndex - 1 : frameIndex - 1;
if (newIndex < 0 || newIndex >= framesMax)
{
frameIndex = framerate < 0 ? framesMax - 1 : 0;
}
}
framerate = -20;
enabled = isPlay = true;
UpdateSprite();
}
}
/// <summary>
/// 播放指定文件路径
/// </summary>
/// <param name="filepath"></param>
public void Play(string filepath)
{
if (string.IsNullOrEmpty(filepath) || framesMax <= 0)
return;
m_Path = filepath;
if (framesMax > 0)
{
if (!enabled && !loop)
{
int newIndex = framerate > 0 ? frameIndex + 1 : frameIndex - 1;
if (newIndex < 0 || newIndex >= framesMax)
{
frameIndex = framerate < 0 ? framesMax - 1 : 0;
}
}
enabled = isPlay = true;
UpdateSprite();
}
}
/// <summary>
/// 暂停播放
/// </summary>
public void Pause()
{
enabled = isPlay = false;
Resources.UnloadUnusedAssets();
}
/// <summary>
/// 停止播放并关闭
/// </summary>
public void Stop()
{
//if (canvasGroup)
//{
// canvasGroup.alpha = 0.0f;
//}
enabled = isPlay = false;
texture = null;
frameIndex = 0;
//m_Path = "";
Resources.UnloadUnusedAssets();
//System.GC.Collect();
}
/// <summary>
/// 从第一帧重新播放
/// </summary>
public void ResetToBeginning()
{
Resources.UnloadAsset(texture);
frameIndex = framerate < 0 ? framesMax - 1 : 0;
isPlay = enabled = true;
UpdateSprite();
}
#endregion
#region 核心逻辑代码
/// <summary>
/// Update使用
/// </summary>
void UpdateRun()
{
if (framesMax == 0)
{
enabled = isPlay = false;
}
else if (framerate != 0)
{
if (isPlay)
{
float time = ignoreTimeScale ? realtime : Time.time;
if (mUpdate < time)
{
mUpdate = time;
int newIndex = framerate > 0 ? frameIndex + 1 : frameIndex - 1;
if (!loop && (newIndex < 0 || newIndex >= framesMax))
{
framerate = 25;
enabled = isPlay = false;
if (EndEvent != null)
EndEvent();
return;
}
frameIndex = RepeatIndex(newIndex, framesMax);
UpdateSprite();
}
}
}
}
/// <summary>
///立即更新可见的精灵。
/// </summary>
void UpdateSprite()
{
if (mUnitySprite == null)
{
if (mUnitySprite == null)
{
enabled = false;
return;
}
}
if (isPlay)
{
//if (canvasGroup && canvasGroup.alpha != 1.0f)
//{
// canvasGroup.alpha = 1.0f;
//}
float time = ignoreTimeScale ? realtime : Time.time;
if (framerate != 0)
{
mUpdate = time + Mathf.Abs(1f / framerate);
}
if (mUnitySprite != null)
{
Resources.UnloadAsset(texture);
texture = (Texture)(Resources.Load(m_Path + "/" + frameIndex.ToString()) as Texture2D);
mUnitySprite.texture = texture;
}
}
}
/// <summary>
/// 使用重复逻辑包装索引,以便例如+1过去,表示索引为'1'。
/// </summary>
//[System.Diagnostics.DebuggerHidden]
//[System.Diagnostics.DebuggerStepThrough]
private int RepeatIndex(int val, int max)
{
if (max < 1) return 0;
while (val < 0) val += max;
while (val >= max)
{
val -= max;
}
return val;
}
#endregion
}
播放序列帧
最新推荐文章于 2024-10-16 10:10:18 发布
这篇博客详细介绍了Unity3D中如何创建和控制序列帧动画。通过`SequenceFrameAnimation`类,实现了对序列帧路径设置、播放、暂停、停止等功能,并通过事件处理播放结束。博客还涉及到了序列帧的帧率调整、循环播放和不受时间缩放影响的播放速度控制。
摘要由CSDN通过智能技术生成