using UnityEngine; using UnityEngine.UI; using System; using System.Collections.Generic; using System.IO; namespace GeneralTools { /// /// 序列帧动画播放器 /// 支持UGUI的Image和Unity2D的SpriteRenderer /// public class FrameAnimator : MonoBehaviour { //目标Image组件 private RawImage image; /// /// 序列帧 /// private List frames = null; /// /// 帧率 /// private float framerate = 24.0f; /// /// 是否忽略timeScale /// private bool ignoreTimeScale = true; /// /// 是否循环 /// private bool loop = true; /// /// 是否允许播放 /// private bool isAllowPlay = false; /// /// 结束事件 /// 在每次播放完一个周期时触发 /// 在循环模式下触发此事件时,当前帧不一定为结束帧 /// public event Action OnFinishEvent; //当前帧索引 private int currentFrameIndex = 0; //下一次更新时间 private float timer = 0.0f; public FrameAnimator Init(List _frames, bool _loop, float _framerate = 24) { Stop(); image = GetComponent(); if (image == null) { Debug.LogError("未找到RawImage", gameObject); } frames = _frames; loop = _loop; framerate = _framerate; image.texture = _frames[0]; OnFinishEvent = null; return this; } public void Play() { isAllowPlay = true; gameObject.SetActive(true); } public void Pause() { isAllowPlay = false; } public void Stop() { isAllowPlay = false; ResetIndex(); } public void Hide() { Stop(); gameObject.SetActive(false); } public void RePlay() { isAllowPlay = false; ResetIndex(); if (frames.Count > 0) { image.texture = frames[currentFrameIndex]; } Play(); } public void SetLoop(bool _loop) { loop = _loop; } /// /// 重设动画索引 /// private int ResetIndex() { currentFrameIndex = framerate > 0 ? 0 : frames.Count - 1; return currentFrameIndex; } void FixedUpdate() { //帧数据无效,禁用脚本 if (frames == null || frames.Count == 0 || image == null || frames.Count == 1 || framerate == 0) { return; } else { //是否允许播放 if (!isAllowPlay) return; //获取当前时间 float time = ignoreTimeScale ? Time.unscaledTime : Time.time; //计算帧间隔时间 float interval = Mathf.Abs(1.0f / framerate); //满足更新条件,执行更新操作 if (time - timer > interval) { //执行更新操作 DoUpdate(); } } } //具体更新操作 private void DoUpdate() { //计算新的索引 int nextIndex = currentFrameIndex + (framerate > 0 ? 1 : -1); //索引越界,表示已经到结束帧 if (nextIndex < 0 || nextIndex >= frames.Count) { //非循环,模式结束 if (loop == false) { isAllowPlay = false; //播放结束事件 OnFinishEvent?.Invoke(); nextIndex = frames.Count - 1; } else { nextIndex = ResetIndex(); } } //钳制索引 currentFrameIndex = Mathf.Clamp(nextIndex, 0, frames.Count - 1); //更新图片 RefreshTexture(currentFrameIndex); //设置计时器为当前时间 timer = ignoreTimeScale ? Time.unscaledTime : Time.time; } private void RefreshTexture(int index) { image.texture = frames[index]; } //正向手动刷新 public void ManualUpdatePositive() { DoUpdate(); } //反向手动刷新 public void ManualUpdateReverse() { framerate *= -1; DoUpdate(); framerate *= -1; } } }