Unity序列帧播放器

  • 核心:
    • 帧率
    • 播放下一帧
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      51
      52
      53
      54
      55
      56
      57
      58
      59
      60
      61
      62
      63
      64
      65
      66
      67
      68
      69
      70
      71
      72
      73
      74
      75
      76
      77
      78
      79
      80
      81
      82
      83
      84
      85
      86
      87
      88
      89
      90
      91
      92
      93
      94
      95
      96
      97
      98
      99
      100
      101
      102
      103
      104
      105
      106
      107
      108
      109
      110
      111
      112
      113
      114
      115
      116
      117
      118
      119
      120
      121
      122
      123
      124
      125
      126
      127
      128
      129
      130
      131
      132
      133
      134
      135
      136
      137
      138
      139
      140
      141
      142
      143
      144
      145
      146
      147
      148
      149
      150
      151
      using UnityEngine;
      using UnityEngine.UI;
      using System;

      /// <summary>
      /// 序列帧动画播放器
      /// 支持UGUI的Image和Unity2D的SpriteRenderer
      /// </summary>
      public class FrameAnimator : MonoBehaviour
      {
      /// <summary>
      /// 序列帧
      /// </summary>
      public Sprite[] Frames{ get { return frames; } set { frames = value; } }

      [SerializeField]private Sprite[] frames = null;

      /// <summary>
      /// 帧率,为正时正向播放,为负时反向播放
      /// </summary>
      public float Framerate { get { return framerate; } set { framerate = value; } }

      [SerializeField] private float framerate = 20.0f;

      /// <summary>
      /// 是否忽略timeScale
      /// </summary>
      public bool IgnoreTimeScale{ get { return ignoreTimeScale; } set { ignoreTimeScale = value; } }

      [SerializeField]private bool ignoreTimeScale = true;

      /// <summary>
      /// 是否循环
      /// </summary>
      public bool Loop{ get { return loop; } set { loop = value; } }

      [SerializeField]private bool loop = true;

      //动画曲线
      [SerializeField]private AnimationCurve curve = new AnimationCurve (new Keyframe (0, 1, 0, 0), new Keyframe (1, 1, 0, 0));

      /// 结束事件
      public event Action FinishEvent;

      //目标Image组件
      private Image image;
      //目标SpriteRenderer组件
      private SpriteRenderer spriteRenderer;
      //当前帧索引
      private int currentFrameIndex = 0;
      //下一次更新时间
      private float timer = 0.0f;
      //当前帧率,通过曲线计算而来
      private float currentFramerate = 20.0f;

      // 重设动画
      public void Reset ()
      {
      currentFrameIndex = framerate < 0 ? frames.Length - 1 : 0;
      }

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

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

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

      //自动开启动画
      void Start ()
      {
      image = this.GetComponent<Image> ();
      spriteRenderer = this.GetComponent<SpriteRenderer> ();

      #if UNITY_EDITOR
      if (image == null && spriteRenderer == null) {
      Debug.LogWarning ("No available component found. 'Image' or 'SpriteRenderer' required.", this.gameObject);
      }
      #endif
      }

      void Update ()
      {
      //帧数据无效,禁用脚本
      if (frames == null || frames.Length == 0) {
      this.enabled = false;
      } else {
      //从曲线值计算当前帧率
      float curveValue = curve.Evaluate ((float)currentFrameIndex / frames.Length);
      float curvedFramerate = curveValue * framerate;
      //帧率有效
      if (curvedFramerate != 0) {
      //获取当前时间
      float time = ignoreTimeScale ? Time.unscaledTime : Time.time;
      //计算帧间隔时间
      float interval = Mathf.Abs (1.0f / curvedFramerate);
      //满足更新条件,执行更新操作
      if (time - timer > interval) {
      //执行更新操作
      DoUpdate ();
      }
      }
      #if UNITY_EDITOR
      else {
      Debug.LogWarning ("Framerate got '0' value, animation stopped.");
      }
      #endif
      }
      }

      //具体更新操作
      private void DoUpdate ()
      {
      //计算新的索引
      int nextIndex = currentFrameIndex + (int)Mathf.Sign (currentFramerate);
      //索引越界,表示已经到结束帧
      if (nextIndex < 0 || nextIndex >= frames.Length) {
      //广播事件
      if (FinishEvent != null) {
      FinishEvent ();
      }
      //非循环模式,禁用脚本
      if (loop == false) {
      currentFrameIndex = Mathf.Clamp (currentFrameIndex, 0, frames.Length - 1);
      this.enabled = false;
      return;
      }
      }
      currentFrameIndex = nextIndex % frames.Length;
      //更新图片
      if (image != null) {
      image.sprite = frames [currentFrameIndex];
      } else if (spriteRenderer != null) {
      spriteRenderer.sprite = frames [currentFrameIndex];
      }
      //设置计时器为当前时间
      timer = ignoreTimeScale ? Time.unscaledTime : Time.time;
      }
      }