播放序列帧

这篇博客详细介绍了Unity3D中如何创建和控制序列帧动画。通过`SequenceFrameAnimation`类,实现了对序列帧路径设置、播放、暂停、停止等功能,并通过事件处理播放结束。博客还涉及到了序列帧的帧率调整、循环播放和不受时间缩放影响的播放速度控制。
摘要由CSDN通过智能技术生成
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
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

土者

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值