Unity播放序列帧

在U3D中播放序列帧应该算是一个非常常见的需求了,基本做过一些正式项目的朋友或多或少都会遇到,包括我自己,所以自己就写了一个非常简单但又好用的播放序列帧的小插件,今天就拿出来给大家分享分享,话不多说直接上图撸代码!

效果展示:

单组序列帧循环播放

多组序列帧顺序播放

OK说一下使用方法,方法很简单几张图一目了然

1.准备序列帧资源

2.在场景中给要播放的Image挂上FramesAnimation.cs脚本​


3.在某个地方存储你要使用Sprite图片组(我这里为了演示图省事直接挂在场景中的的Test脚本上了,你们可以根据需要自动加载配置等)

4.然后调用播放方法(list1为你传入的图片数组,true表示循环)

OK下面放上源码

```


using System.Collections;

using System.Collections.Generic;

using System.IO;

using UnityEngine;

using UnityEngine.Events;

using UnityEngine.UI;

public class FramesAnimation : MonoBehaviour

{

    protected enum anim_status

    {

        unstart,

        running,

        pause,

        stop

    }

    protected Image image

    {

        get

        {

            return GetComponent();

        }

    }

    //当前的序列帧动画

    public List image_list = new List();

    //一串连续播放的序列帧动画组

    public List> Sequence = new List>();

    //当前播放的序列帧ID(如果ID=-1,则不播放序列帧动画。其他时按照ID来播放动画,播完一个动画自动切到下一个动画,全部播完时停留在最后一个动画)

    protected int SequenceID = -1;

    protected bool loop = true;

    protected anim_status status;

    protected UnityAction onComplete;

    //添加动画完成事件,动画第一次循环结束时执行

    public void OnComplete(UnityAction _event)

    {

        onComplete = _event;

    }

    //动画停止时执行一次。

    protected UnityAction EndEvent;

    public void SetEndEvent(UnityAction _event)

    {

        EndEvent = _event;

    }

    //动画每次循环都执行

    protected UnityAction CircleEvent;

    public void SetCircleEvent(UnityAction _event)

    {

        CircleEvent = _event;

    }

    protected UnityAction Change_event;

    //当前帧索引

    private int currentFrameIndex = 0;

    //动画帧率

    private float Framerate = 20.0f;

    void Update()

    {

        if (status == anim_status.running)

        {

            //按帧率播放

            if (Time.frameCount % (30 / Framerate) == 0)

            {

                currentFrameIndex++;

            }

            //第一次播放结束

            if (currentFrameIndex >= image_list.Count)

            {

                SequenceRule();

                currentFrameIndex = 0;

                CircleEvent?.Invoke();

                onComplete?.Invoke();

                if (onComplete != null)

                {

                    onComplete = null;

                }

                Change_event?.Invoke();

                if (!loop && SequenceID == -1)

                {

                    status = anim_status.stop;

                    //停在最后一帧

                    currentFrameIndex = image_list.Count - 1;

                }

            }

            if (image_list.Count != 0)

            {

                image.sprite = image_list[currentFrameIndex];

            }

            else

            {

                Debug.LogError("动画序列帧为空!");

            }

        }

    }

    public void ClearSequence()

    {

        status = anim_status.stop;

        image_list.Clear();

        Sequence.Clear();

    }

    void SequenceRule()

    {

        if (SequenceID != -1)

        {

            if (SequenceID < Sequence.Count - 1)

            {

                image_list.Clear();

                SequenceID++;

                Sequence[SequenceID].ForEach(i => image_list.Add(i));

            }

            else

            {

                SequenceID = -1;

            }

        }

    }

    ///

    /// 多组序列帧播放

    ///

    /// 传入的多组图片

    public void AnimPlaySequence(List> _sequence)

    {

        ClearSequence();

        SequenceID = 0;

        currentFrameIndex = 0;

        foreach (List _list in _sequence)

        {

            Sequence.Add(_list);

        }

        Sequence[0].ForEach(i => image_list.Add(i));

        image.sprite = image_list[0];

        loop = true;

        status = anim_status.running;

    }

    public void AnimPlay(List _list, bool _loop = false, int frame = 0)

    {

        ClearSequence();

        SequenceID = 0;

        currentFrameIndex = 0;

        _list.ForEach(i => image_list.Add(i));

        image.sprite = image_list[0];

        loop = _loop;

        currentFrameIndex = frame;

        status = anim_status.running;

    }

    public void AnimPause()

    {

        status = anim_status.pause;

    }

    public void AnimContinue()

    {

        status = anim_status.running;

    }

    public void AnimReplay()

    {

        currentFrameIndex = 0;

    }

    public void AnimStop()

    {

        status = anim_status.stop;

        currentFrameIndex = 0;

        EndEvent?.Invoke();

    }

    public void ChangeClip(List new_list, bool Immediately = false)

    {

        Change_event = delegate

        {

            image_list.Clear();

            new_list.ForEach(i => image_list.Add(i));

        };

        if (Immediately)

        {

            Change_event?.Invoke();

        }

        else

        {

            Change_event += delegate

            {

                Change_event = null;

            };

        }

    }

}


```

代码中基本功能都差不多已经有了,包括:

1.帧率的设定

2.是否受TimeScale影响

3.不同播放节点的回调

序列帧播放的原理没啥好说的,Update里按照一定的帧率或时间逐帧切换图片。

但下面额外讲讲AnimPlaySequence()这个方法

如果你只是用一组序列帧播放的话AnimPlay()就很方便使用了,

但我们播放的需求往往没有这么简单,往往是多组序列帧来回切换或拼接播放的,那么你就可以使用队列播放这个方法

_sequence这个参数就是传入的多组图片

调用这个方法动画就会按照你传入的数组顺序播放,然后在最后一组动画内循环播放(各位可按需修改为需要的效果)

OK内容差不多就是这些了,上面GIF的效果我做成了Demo上传到了Github上,有需要的朋友可以前去自行下载。传送门

原创不易!转发的朋友记得加上转载声明哦,喜欢的朋友可以顺手点个赞哈,谢谢啦!

你可能感兴趣的:(Unity播放序列帧)