Unity3D的2D帧动画控制工具编写

前些日子公司让笔者写了一个帧动画控制工具,主要是用来控制聊天表情这些2D动画的,原本想偷懒在网上直接考了一份代码,没想到运行之后发现当帧率为负的时候还有bug,最后在他基础上做了改动,优化了一下并把bug修复了。

原文链接 https://blog.csdn.net/serenahaven/article/details/79273114

把每一帧的图片按顺序拖进数组中,设置好参数

每个参数注释已经写的非常详细了,直接贴代码吧。

using System;
using UnityEngine;
using UnityEngine.UI;

public class Animation2D : MonoBehaviour {

    /// <summary>
    /// 帧率
    /// 为正时正向播放,为负时反向播放
    /// </summary>
    public float frameRate = 2;

    /// <summary>
    /// 延时播放
    /// </summary>
    public float delayTime=0;

    /// <summary>
    /// 动画曲线
    /// </summary>
    public AnimationCurve curve = new AnimationCurve(new Keyframe(0, 1, 0, 0), new Keyframe(1, 1, 0, 0));

    /// <summary>
	/// 结束事件
	/// 在每次播放完一个周期时触发
	/// 在循环模式下触发此事件时,当前帧不一定为结束帧
	/// </summary>
	public event Action FinishEvent;

    /// <summary>
    /// 动画是否循环播放
    /// </summary>
    public bool loop = true;

    /// <summary>
    /// 播放结束是否销毁
    /// </summary>
    public bool isEndDstory = false;

    /// <summary>
    /// 序列帧
    /// </summary>
    public Sprite[] frameSprites;

    //************************************************

    //显示的图片
    private Image image;

    //当前帧
    private int currentFrameIndex=0;

    //计时器
    private float timer = 0;

    // Use this for initialization
    void Start ()
    {
        image = GetComponent<Image>();
#if UNITY_EDITOR
        if (image == null)
            Debug.LogError("请挂载 Image 组件,");
#endif
        if(delayTime==0) image.sprite = frameSprites[currentFrameIndex];
    }
	
	// Update is called once per frame
	void Update ()
    {
        if (image != null && frameRate != 0&&Time.time>=delayTime)
        {
            //计算  实际帧率=帧率*曲线值(由曲线横坐标,取得纵坐标的值)
            float value = curve.Evaluate((float)currentFrameIndex / frameSprites.Length);
            float actualFrameRate = value * frameRate;
            if (actualFrameRate != 0)
            {
                //获取当前游戏运行时间
                float time = Time.time;
                //计算帧间隔时间
                float interval = Mathf.Abs(1.0f / actualFrameRate);
                //满足更新条件,执行更新操作
                if (time - timer > interval)//大于时间间隔,执行更新
                {
                    //计算新的索引 Mathf.Sign(float f) f为正返回1,为负返回-1
                    int nextIndex = currentFrameIndex + (int)Mathf.Sign(actualFrameRate);
                    //索引越界,表示已经到结束帧
                    if ((nextIndex <=-frameSprites.Length&& frameRate<0) || nextIndex >= frameSprites.Length)
                    {
                        //触发事件
                        if (FinishEvent != null) FinishEvent();                 
                        //非循环模式
                        if (!loop)
                        {
                            if (isEndDstory)//动画播放结束时销毁
                                Destroy(this.gameObject);
                            currentFrameIndex = Mathf.Clamp(currentFrameIndex, 0, frameSprites.Length-1);
                            this.enabled = false;
                            return;
                        }
                    }
                    //钳制索引
                    currentFrameIndex =frameRate<0? (frameSprites.Length+nextIndex) % frameSprites.Length : nextIndex % frameSprites.Length;
                    //更新当前帧图片
                    image.sprite = frameSprites[currentFrameIndex];
                    //设置计时器为当前时间
                    timer = Time.time;
                }
            }

        }
	}

    /// <summary>
	/// 重设动画
	/// </summary>
	public void Reset()
    {
        currentFrameIndex = frameRate < 0 ? frameSprites.Length - 1 : 0;
    }

    /// <summary>
    /// 从停止的位置播放动画
    /// </summary>
    public void Play()
    {
        this.enabled = true;
    }

    /// <summary>
    /// 暂停动画
    /// </summary>
    public void Pause()
    {
        this.enabled = false;
    }

    /// <summary>
    /// 停止动画,将位置设为初始位置
    /// </summary>
    public void Stop()
    {
        Pause();
        Reset();
    }
}

猜你喜欢

转载自blog.csdn.net/qq_39824797/article/details/83820970