动画帧管理

在我们进行开发时,需要对物体进行动画帧处理,常规处理方式为创建animation,对animation进行处理
在这里插入图片描述

这是通过脚本对图片进行控制

using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Networking;
using UnityEngine.UI;


public enum LoadMode
{
    Resources,
    StreamingAssets,
    AssetBundle
}

public enum PlayMode
{
    None,
    Normal,
    Inverse,
}

[RequireComponent(typeof(RawImage))]
public class AnimationBase : MonoBehaviour, IDragHandler, IBeginDragHandler, IEndDragHandler
{
    [HideInInspector]
    public RawImage img;

    public LoadMode loadMode;

    [SerializeField]
    private PlayMode playMode = PlayMode.Normal;

    #region 三种加载方式共有参数
    [HideInInspector] public List<Texture> textures;
    public bool isAutoPlay;
    public bool unScaleTime;
    [Tooltip("自动播放时每张图片索引的间隔")]
    public bool canDrag;
    public float sample_Win = 30;
    private float sample;
    public string path;
    public int aniStartIndex;
    public int aniLastIndex;
    public int textureInterval = 1;
    [Tooltip("滑动时每张图片索引的间隔")]
    public int dragInterval = 1;
    //[Tooltip("图片路径中零的个数")]
    public int zeroCount;
    public float delayTime;
    public bool isLoop;
    [Tooltip("是否有间隔的循环")]
    public bool isExtendLoop;
    [Tooltip("每次循环间隔时间")]
    public float loopTime;
    private int index;
    [HideInInspector]
    public float animationTime;
    protected int dir = 1;
    private bool isPlaying;
    private DateTime startUpTime = new DateTime(1970, 1, 1, 0, 0, 0, 0);
    private double nowTime;
    public delegate void AnimationDoneEventHandler();
    /// <summary>
    /// 只播放一次的序列,序列结束事件
    /// </summary>
    public event AnimationDoneEventHandler AnimationOnceDoneEvent;
    /// <summary>
    /// 循环播放的序列,序列结束事件
    /// </summary>
    public event Action AnimationPerLoopDoneEvent;
    public event Action BeginDragEvent;
    public event Action EndDragEvent;
    public event Action OnDragEvent;
    public event Action PlayToDoneEvent;

    protected bool isDraging;
    #endregion

    #region StreamingAssets加载方式参数,存在内存泄漏问题,尽量避免使用
    / <summary>
    / 图片检索格式
    / </summary>
    //[Tooltip("图片格式,例如:png、jpg")]
    //public string pattern;
    / <summary>
    / 图片路径后缀
    / </summary>
    //[Tooltip("路径索引号后缀,例如:001_00050(-\"fs8\")")]
    [HideInInspector] public string suffix;

    private List<FileInfo> fileInfos;
    #endregion

    #region AssetBundle加载方式参数
    private AssetBundle textureBundle;
    private string[] assetsName;
    #endregion

    public int Index
    {
        set
        {
            index = value;
            if (((index == aniLastIndex - textureInterval) && playMode == PlayMode.Normal) || (index == aniStartIndex && playMode == PlayMode.Inverse))
            {
                if (isExtendLoop)
                {
                    //InitIndex();
                    ExtendLoop();
                    if (AnimationPerLoopDoneEvent != null)
                        AnimationPerLoopDoneEvent();
                }
                else if (isLoop)
                {
                    if (AnimationPerLoopDoneEvent != null)
                        AnimationPerLoopDoneEvent();
                }
            }
            if (index >= aniLastIndex && isLoop)
            {
                index = aniStartIndex;
            }
            else if (index < 0 && isLoop)
            {
                index = aniLastIndex - textureInterval;
            }
            else if (((index >= aniLastIndex - textureInterval) && !isLoop && playMode == PlayMode.Normal) || ((index <= aniStartIndex) && !isLoop && playMode == PlayMode.Inverse))
            {
                Pause();
                if (AnimationOnceDoneEvent != null)
                {
                    AnimationOnceDoneEvent();
                }
            }
        }
        get
        {
            return index;
        }
    }

    //public static AnimationBase Instance { private set; get; }

    private void OnEnable()
    {
        InitTimer();
        if (isExtendLoop)
            Play(loopTime);
    }

    private void Awake()
    {
        Init();
    }


    protected virtual void Start()
    {
        //Instance = this;
        //GetAnimationCount();
        InitIndex();
        SetSample(sample_Win);
        LoadAssetBundle();
        GetAnimationTime();
        AutoPlay();
        EnrolEvent();
    }
    private bool isOpen = false;
    public RawImage  Anim;
    public Sprite[] sprites; // 存储图片的数组 
    public static void OnButtonClicTest()
    {
        Debug.Log("666");
    }
    public void OnButtonClick()
    {
        isOpen = !isOpen;

        if (isOpen)
        {
        
     //       Debug.Log("789" + index);
            Anim.gameObject.SetActive(true);
                 
            //  Replay();
            Replay();
           
            Debug.Log("11111");
        }
        else
        {
            RawImage rawImage = GetComponent<RawImage>();
            Texture2D tex = rawImage.texture as Texture2D; //获取截图的位置和大小
             Rect rect = new Rect(0, 0, 100, 100); //创建截图
            Texture2D newTex = new Texture2D((int)rect.width, (int)rect.height); //获取截图数据
             Color[] colors = tex.GetPixels((int)rect.x, (int)rect.y, (int)rect.width, (int)rect.height); //将数据设置到新纹理中
            newTex.SetPixels(colors); //应用修改
            newTex.Apply(); //将截图设置到RawImage中 rawImage.texture = newTex;
            Anim.texture = newTex;
            index = 0;
            Anim.gameObject.SetActive(false);
            
            Debug.Log("22222");
        }
    }

    private void AutoPlay()
    {
        if (isAutoPlay)
            Play(delayTime);
    }

    private void Init()
    {
        img = GetComponent<RawImage>();
        textures = new List<Texture>();
        fileInfos = new List<FileInfo>();
        if (playMode == PlayMode.Normal)
        {
            dir = 1;
        }
        else
        {
            dir = -1;
        }

        if (loadMode == LoadMode.Resources && !string.IsNullOrEmpty(path))
        {
            Texture[] tempTex = Resources.LoadAll<Texture>(path);
            if (tempTex.Length == 0) return;
            //Array.Sort(tempTex, (a, b) => DrawNumFromString(a.name, '_').CompareTo(DrawNumFromString(b.name, '_')));
            textures.AddRange(tempTex);
            aniLastIndex = textures.Count;
        }
        else if (loadMode == LoadMode.StreamingAssets)
        {
#if UNITY_STANDALONE_WIN
            fileInfos.Clear();
            FileInfo[] files = null;
            string filePath = Application.streamingAssetsPath + "/" + path;
            files = new DirectoryInfo(filePath).GetFiles();
#endif
            //Array.Sort(files, (a, b) => DrawNumFromString(a.Name, '_').CompareTo(DrawNumFromString(b.Name, '_')));
#if UNITY_EDITOR&&!UNITY_IOS&&!UNITY_ANDROID
            if (files != null)
            {
                for (int i = 0; i < files.Length; i++)
                {
                    if (files[i].Name.Contains(".meta")) continue;
                    fileInfos.Add(files[i]);
                }
                aniLastIndex = fileInfos.Count;
            }
#elif UNITY_STANDALONE_WIN
            fileInfos.AddRange(files);
            aniLastIndex = fileInfos.Count;
#endif
        }
    }

    public void InitIndex()
    {
        Index = aniStartIndex;
    }

    private void InitTimer()
    {
        nowTime = GetUtcMiliseconds();
        timer = nowTime + sample;
    }

    protected virtual void EnrolEvent()
    {
        //AnimationDoneEvent += ExtendLoop;
    }

    protected virtual void CancelEvent()
    {
        //AnimationDoneEvent -= ExtendLoop;
    }

    private void OnDestroy()
    {
        CancelEvent();
        AssetBundle.UnloadAllAssetBundles(true);
    }

    private void ExtendLoop()
    {
        Pause();
        Play(loopTime);
    }

    protected void LoadAssetBundle()
    {
        if (loadMode == LoadMode.AssetBundle && !string.IsNullOrEmpty(path))
        {
            string tempPath = Application.streamingAssetsPath + "/" + path;
            textureBundle = AssetBundle.LoadFromFile(tempPath);
            assetsName = textureBundle.GetAllAssetNames();
            aniLastIndex = assetsName.Length;
        }
    }

    protected void LoadAnimation()
    {
        if (!isDraging)
        {
            Index += textureInterval * dir;
        }

        if (isPlayTo)
        {
            if (Index == toIndex)
            {
                Pause();
                canDrag = true;
                PlayToDoneEvent?.Invoke();
            }
        }

        if (loadMode == LoadMode.Resources)
        {
            //Texture texture = Resources.Load<Texture>(path + string.Format("{0:D" + zeroCount + "}", Index) + suffix);

            Texture texture = textures[Index];

            if (texture)
                img.texture = texture;
            else
                Debug.LogError("动画路径错误");
        }
        else if (loadMode == LoadMode.StreamingAssets)
        {
            //StartCoroutine(nameof(GetTexture), Application.streamingAssetsPath + "/" + path + string.Format("{0:D" + zeroCount + "}", Index) + suffix);

            //StartCoroutine(nameof(GetTexture), fileInfos[Index].FullName);

#if UNITY_STANDALONE_WIN
            string tempPath = Application.streamingAssetsPath + "/" + path + "/" + fileInfos[Index].Name;
            //string tempPath = Application.streamingAssetsPath + "/" + path+string.Format("{0:D"+zeroCount+"}",Index)+suffix;
#elif UNITY_IOS || UNITY_ANDROID
            string tempPath = Application.streamingAssetsPath + "/" + path+string.Format("{0:D"+zeroCount+"}",Index)+suffix;
#endif
#if UNITY_STANDALONE_WIN || UNITY_IOS
            Texture texture = LoadTexture(tempPath);

            if (texture)
            {
                img.texture = texture;
            }
            else
            {
                Debug.LogError("动画路径错误");
            }
#elif UNITY_ANDROID
            StartCoroutine(nameof(GetTexture), tempPath);
#endif

        }
        else
        {
            img.texture = textureBundle.LoadAsset<Texture>(assetsName[Index]);
        }
        Resources.UnloadUnusedAssets();
    }

    private IEnumerator GetTexture(string name)
    {
        using (UnityWebRequest uwrt = UnityWebRequestTexture.GetTexture(name))
        {
            yield return uwrt.SendWebRequest();
            if (!string.IsNullOrEmpty(uwrt.error))
            {
                Debug.LogError(uwrt.error);
            }
            else
            {
                img.texture = DownloadHandlerTexture.GetContent(uwrt);
                img.SetNativeSize();
                //System.GC.Collect();
            }
        }
    }

    private Texture LoadTexture(string path)
    {
        using (FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read))
        {
            fs.Seek(0, SeekOrigin.Begin);
            byte[] data = new byte[fs.Length];
            fs.Read(data, 0, data.Length);
            Texture2D texture = new Texture2D(100, 100, TextureFormat.ARGB32, false);
            texture.LoadImage(data);
            if (texture)
            {
                texture.name = Index.ToString();
                return texture;
            }
            else
            {
                return null;
            }
        }
    }

    private double timer;
    private bool isStartPlay;
    private void Update()
    {
        CheckAnimation();
    }

    private void CheckAnimation()
    {
        if (isStartPlay || isPlayTo)
        {
            nowTime = GetUtcMiliseconds();
            if (nowTime.CompareTo(timer) > 0)
            {
                timer = GetUtcMiliseconds();
                timer += sample;
                LoadAnimation();
            }
        }
    }

    private IEnumerator DelayPlay(float delay)
    {
        yield return new WaitForSeconds(delay);
        InitIndex();
        nowTime = GetUtcMiliseconds();
        timer = nowTime + sample;
        isStartPlay = true;
        isPlaying = true;
    }

    public virtual void OnBeginDrag(PointerEventData eventData)
    {
        if (!canDrag || Input.touchCount > 1) return;
        isDraging = true;
        isStartPlay = false;
        BeginDragEvent?.Invoke();
    }

    public virtual void OnDrag(PointerEventData eventData)
    {
        if (!canDrag || Input.touchCount > 1) return;

        if (eventData.delta.x < 0)
        {
            dir = -1;
            dragInterval = Mathf.Clamp(Mathf.RoundToInt(Mathf.Abs(eventData.delta.x) * Time.deltaTime), 1, 5);
            Index -= dragInterval;
        }
        else if (eventData.delta.x > 0)
        {
            dir = 1;
            dragInterval = Mathf.Clamp(Mathf.RoundToInt(eventData.delta.x * Time.deltaTime), 1, 5);
            Index += dragInterval;
        }

        if (!isLoop || !isExtendLoop)
        {
            Index = Mathf.Clamp(Index, aniStartIndex, aniLastIndex - 1);
        }
        OnDragEvent?.Invoke();
        LoadAnimation();
    }

    public virtual void OnEndDrag(PointerEventData eventData)
    {
        if (!canDrag || Input.touchCount > 1) return;
        isDraging = false;
        EndDragEvent?.Invoke();
    }

    #region ToolMethod

    private int DrawNumFromString(string str, char splitChar)
    {
        int index = str.LastIndexOf(splitChar);
        return int.Parse(System.Text.RegularExpressions.Regex.Replace(str.Substring(index), @"[^0-9]+", ""));
    }

    private double GetUtcMiliseconds()
    {
        TimeSpan ts = DateTime.UtcNow - startUpTime;
        return ts.TotalMilliseconds;
    }

    public void SetSample(float val)
    {
        sample = 1.0f / val * 1000;
        nowTime = GetUtcMiliseconds();
        timer = nowTime + sample;
    }

    public void SetAssetBundle(AssetBundle bundle)
    {
        textureBundle = bundle;
        assetsName = textureBundle.GetAllAssetNames();
        aniLastIndex = assetsName.Length;
    }

    public void SetLoadMode(LoadMode model)
    {
        loadMode = model;
    }

    public void ChangePath(string path, int aniStartIndex, int aniLastIndex)
    {
        this.path = path;
        this.aniStartIndex = aniStartIndex;
        this.aniLastIndex = aniLastIndex;
        Index = aniStartIndex;
        if (loadMode == LoadMode.StreamingAssets)
        {
#if UNITY_STANDALONE_WIN
            fileInfos.Clear();
            FileInfo[] files = null;
            string filePath = Application.streamingAssetsPath + "/" + path;
            files = new DirectoryInfo(filePath).GetFiles();
#endif
            //Array.Sort(files, (a, b) => DrawNumFromString(a.Name, '_').CompareTo(DrawNumFromString(b.Name, '_')));
#if UNITY_EDITOR&&!UNITY_IOS&&!UNITY_ANDROID
            if (files != null)
            {
                for (int i = 0; i < files.Length; i++)
                {
                    if (files[i].Name.Contains(".meta")) continue;
                    fileInfos.Add(files[i]);
                }
                this.aniLastIndex = fileInfos.Count;
            }
#elif UNITY_STANDALONE_WIN
            fileInfos.AddRange(files);
            this.aniLastIndex = fileInfos.Count;
#endif

#if UNITY_STANDALONE_WIN
            string tempPath = Application.streamingAssetsPath + "/" + path + "/" + fileInfos[Index].Name;
            //string tempPath = Application.streamingAssetsPath + "/" + path + string.Format("{0:D" + zeroCount + "}", Index) + suffix;
#elif UNITY_IOS || UNITY_ANDROID
            string tempPath = Application.streamingAssetsPath + "/" + path+ string.Format("{0:D" + zeroCount + "}", Index) + suffix;
#endif

#if UNITY_STANDALONE_WIN || UNITY_IOS
            Texture texture = LoadTexture(tempPath);

            if (texture)
                img.texture = texture;
            else
                Debug.LogError("动画路径错误");
#elif UNITY_ANDROID
            StartCoroutine(nameof(GetTexture), tempPath);
#endif
        }
        else if (loadMode == LoadMode.Resources)
        {
            textures.Clear();

            textures.AddRange(Resources.LoadAll<Texture>(path));

            this.aniLastIndex = textures.Count;

            //Texture texture = Resources.Load<Texture>(path + string.Format("{0:D" + zeroCount + "}", Index) + suffix);            

            Texture texture = textures[Index];

            if (texture)
                img.texture = texture;
            else
                Debug.LogError("动画路径错误");
        }
        else
        {
            AssetBundle.UnloadAllAssetBundles(true);
            string tempPath = Application.streamingAssetsPath + "/" + path;
            textureBundle = AssetBundle.LoadFromFile(tempPath);
            assetsName = textureBundle.GetAllAssetNames();
            this.aniLastIndex = assetsName.Length;
            img.texture = textureBundle.LoadAsset<Texture>(assetsName[Index]);
        }
        img.SetNativeSize();
        Resources.UnloadUnusedAssets();
    }

    public float GetProgress()
    {
        return Index / aniLastIndex * 1.0f;
    }

    public void GetAnimationTime()
    {
        animationTime = aniLastIndex * sample / 1000;
    }
    public void Pause()
    {
        isPlaying = false;
        isStartPlay = false;
        isPlayTo = false;
    }

    public void Play(float delay = 0, PlayMode mode = PlayMode.None)
    {
        if (isPlaying) return;
        if (mode != PlayMode.None)
            playMode = mode;
        if (playMode == PlayMode.Normal)
            dir = 1;
        else
            dir = -1;

        StopAllCoroutines();
        StartCoroutine(DelayPlay(delay));
    }

    public void Replay(float delay = 0, PlayMode mode = PlayMode.Normal)
    {
        //if (isPlaying) return;
        playMode = mode;
        if (playMode == PlayMode.Normal)
            dir = 1;
        else
            dir = -1;
        //InitIndex();
        Debug.Log("123456");
        StopAllCoroutines();
        StartCoroutine(DelayPlay(delay));
    }

    private bool isPlayTo;
    private int toIndex;
    public void PlayTo(int to, int from = 0)
    {
        if (isPlayTo) return;
        if ((to >= aniLastIndex) || (from >= aniLastIndex) || from < 0 || to < 0)
        {
            Debug.LogError("超出序列范围");
            return;
        }
        if (from != 0)
        {
            Index = from;
        }
        PlayMode mode = from <= to ? PlayMode.Normal : PlayMode.Inverse;
        SetPlayMode(mode);
        isPlayTo = true;
        canDrag = false;
        toIndex = to;
    }

    public void ClearPlayToEvent()
    {
        PlayToDoneEvent = null;
    }

    public void ClearBeginDragEvent()
    {
        BeginDragEvent = null;
    }

    public void ClearEndDragEvent()
    {
        EndDragEvent = null;
    }

    public void ClearOnDragEvent()
    {
        OnDragEvent = null;
    }

    public void ClearAllEvent()
    {
        AnimationPerLoopDoneEvent = null;
        AnimationOnceDoneEvent = null;
        BeginDragEvent = null;
        EndDragEvent = null;
        PlayToDoneEvent = null;
        OnDragEvent = null;
    }

    public void SetPlayMode(PlayMode mode)
    {
        playMode = mode;
        if (mode == PlayMode.Normal)
            dir = 1;
        else
            dir = -1;
    }

    public void SetCurrentIndex(int index)
    {
        Index = index;
    }

    public void ChangeCurtSprite()
    {
        Texture texture = textures[0];
        img.texture = texture;
    }
    #endregion
}

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值