一:使用

Unity中实现播放2D序列帧特效(内存优化版)_经验分享


二:实现

using UnityEngine;
using UnityEngine.UI;
using System;
using System.Collections.Generic;

/// <summary>
/// 2D序列帧特效
/// </summary>
public class UI_2DEffect : MonoBehaviour
{
    private Image img;//图片组件

    [Header("资源目录")]
    public string resDir;

    [Header("总帧数")]
    [Space(25)]
    public int totalFarme;
    [Header("帧率")]
    public int frameRate;

    [Header("是否自动播放")]
    [Space(25)]
    public bool autoPlay = false;
    [Header("是否循环播放")]
    public bool isLoop = false;

    private Sprite curSprite;//当前Sprite
    private int curFrame;//当前帧
    private float timer;//计时器
    private bool isPlaying;//是否在播放

    private Dictionary<int, Action> eventDict = new Dictionary<int, Action>();//存储事件的字典

    #region Init

    private void Awake()
    {
        img = GetComponent<Image>();
        img.enabled = false;
    }

    private void Start()
    {
        if (autoPlay)
        {
            Play();
        }
    }

    #endregion

    #region Main

    /// <summary>
    /// 注册事件
    /// </summary>
    public void RegisterEvent(int eventFrame, Action onFinish)
    {
        if (!eventDict.ContainsKey(eventFrame))
        {
            eventDict.Add(eventFrame, onFinish);
        }
    }

    /// <summary>
    /// 播放
    /// </summary>
    public void Play()
    {
        timer = 1f / frameRate;
        curFrame = 0;
        curSprite = null;
        img.enabled = true;
        img.sprite = null;
        isPlaying = true;
    }

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

    /// <summary>
    /// 继续
    /// </summary>
    public void Resume()
    {
        isPlaying = true;
    }

    /// <summary>
    /// 停止
    /// </summary>
    public void Stop()
    {
        img.enabled = false;
        isPlaying = false;

        //清除结束的事件
        ClearFinishEvent();
        //卸载资源
        Unload();
    }

    #endregion

    #region Misc

    /// <summary>
    /// 检测事件
    /// </summary>
    private void CheckEvent()
    {
        int tempKey = -1;

        foreach (var temp in eventDict)
        {
            if (curFrame == temp.Key)
            {
                tempKey = temp.Key;
                eventDict[temp.Key]?.Invoke();
            }
        }

        eventDict.Remove(tempKey);
    }

    /// <summary>
    /// 检测播放
    /// </summary>
    private void CheckPlay()
    {
        if (isPlaying == false)
        {
            return;
        }

        timer += Time.fixedDeltaTime;
        if (timer >= 1f / frameRate)
        {
            //播放下一帧
            PlayNextFrame();
            timer = 0;
        }
    }

    /// <summary>
    /// 播放下一帧
    /// </summary>
    private void PlayNextFrame()
    {
        if (curFrame >= totalFarme)
        {
            //停止
            Stop();

            if (isLoop)
            {
                Play();
            }
            return;
        }

        if (curSprite != null)
        {
            //卸载资源
            Unload();
        }

        string path = resDir + "/" + curFrame;
        curSprite = Resources.Load<Sprite>(path);
        if (curSprite == null)
        {
            Debug.LogWarning("没有此图片:" + path);
        }
        else
        {
            img.sprite = curSprite;
            curFrame++;
        }
    }

    /// <summary>
    /// 卸载资源
    /// </summary>
    private void Unload()
    {
        curSprite = null;
        img.sprite = null;
        Resources.UnloadUnusedAssets();
    }

    /// <summary>
    /// 清除结束的事件
    /// </summary>
    private void ClearFinishEvent()
    {
        eventDict.Clear();
    }

    private void FixedUpdate()
    {
        //检测事件
        CheckEvent();
        //检测播放
        CheckPlay();
    }

    #endregion
}

三:Resources.UnloadUnusedAssets的用法