using UnityEngine; using UnityEngine.UI; using System; using System.Collections.Generic; using System.IO; using System.Linq; namespace GeneralTools { /// /// 序列帧动画播放器 /// 支持UGUI的Image和Unity2D的SpriteRenderer /// public class FramesAnimator : MonoBehaviour { //目标Image组件 private RawImage image; private List framesList; /// /// 全部结束事件 /// public event Action OnAllFinishEvent; //是否允许播放 private bool isAllowPlay = true; //当前帧索引 private int currentFrameIndex = 0; //当前动画序号索引 private int currentAnimationIndex = 0; //下一次更新时间 private float timer = 0.0f; public FramesAnimator Init(List frameAttritubes) { Stop(); image = GetComponent(); if (image == null) { Debug.LogError("未找到RawImage", gameObject); } framesList = frameAttritubes; OnAllFinishEvent = null; return this; } public FramesAnimator Init(params List[] texArr) { List temp = new List(); for (int i = 0; i < texArr.Length; i++) { FramesAttribute newFM = new FramesAttribute(texArr[i], i == texArr.Length - 1); temp.Add(newFM); } return Init(temp); } public FramesAnimator Init(List> texList, List loopList, List finishEventList = null) { List temp = new List(); if (finishEventList == null) finishEventList = new List(); for (int i = 0; i < texList.Count; i++) { bool il = i < loopList.Count ? loopList[i] : false; FramesAttribute newFM = new FramesAttribute(texList[i], il); newFM.OnFinishEvent += i < finishEventList.Count ? finishEventList[i] : null; temp.Add(newFM); } return Init(temp); } 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 (framesList.Count > 0) { if (framesList[0].framesList.Count > 0) { image.texture = framesList[0].framesList[currentFrameIndex]; } } Play(); } public void PlayIndex(int index) { if (framesList == null) return; if (index < 0 || index >= framesList.Count) return; isAllowPlay = false; currentAnimationIndex = index; currentFrameIndex = framesList[currentAnimationIndex].framerate > 0 ? 0 : framesList[currentAnimationIndex].framesList.Count - 1; if (framesList[currentAnimationIndex].framesList.Count > 0) { image.texture = framesList[currentAnimationIndex].framesList[currentFrameIndex]; } Play(); } /// /// 改变一个索引的临时loop /// public void SetLoopOfIndex(int index, bool loop) { if (index >= 0 && index < framesList.Count) { framesList[index].loop = loop; } } /// /// 改变一个索引的永久loop /// public void SetLoopOfIndexForever(int index, bool loop) { if (index >= 0 && index < framesList.Count) { framesList[index].InitialLoop = loop; } } /// /// 获得当前动画索引 /// public int GetCurrentAnimationIndex() { return currentAnimationIndex; } /// /// 改变当前索引的临时loop /// public void SetCurrentAnimationLoop(bool loop) { SetLoopOfIndex(currentAnimationIndex, loop); } /// /// 动画全部设置为不循环,播放完销毁自身 /// public void GoDestroy() { for (int i = 0; i < framesList.Count; i++) { SetLoopOfIndexForever(i, false); } OnAllFinishEvent += () => { Destroy(gameObject); }; } /// /// 重设动画索引 /// private int ResetIndex() { currentAnimationIndex = 0; //重置Loop if (framesList != null) { for (int i = 0; i < framesList.Count; i++) { framesList[i].ReSetLoop(); } currentFrameIndex = framesList[currentAnimationIndex].framerate > 0 ? 0 : framesList[currentAnimationIndex].framesList.Count - 1; } return currentFrameIndex; } void FixedUpdate() { if (framesList == null || framesList.Count == 0 || image == null) { return; } else { //是否允许播放 if (!isAllowPlay) return; PlayOneFrame(framesList[currentAnimationIndex]); } } private void PlayOneFrame(FramesAttribute fm) { if (fm == null || fm.framesList.Count == 0 || fm.framerate == 0) { return; } //获取当前时间 float time = fm.ignoreTimeScale ? Time.unscaledTime : Time.time; //计算帧间隔时间 float interval = Mathf.Abs(1.0f / fm.framerate); //满足更新条件,执行更新操作 if (time - timer > interval) { //执行更新操作 DoUpdate(fm); } } //具体更新操作 private void DoUpdate(FramesAttribute fm) { //计算新的索引 int nextIndex = currentFrameIndex + (fm.framerate > 0 ? 1 : -1); //索引越界,表示已经到结束帧 if (nextIndex < 0 || nextIndex >= fm.framesList.Count) { nextIndex = 0; //不循环,整体动画索引+1 if (fm.loop == false) { //播放结束事件 fm.OnFinish(); currentAnimationIndex += 1; if (currentAnimationIndex >= framesList.Count) { //全部播放完毕,帧索引不归零 isAllowPlay = false; OnAllFinishEvent?.Invoke(); currentAnimationIndex = framesList.Count - 1; nextIndex = fm.framesList.Count - 1; } else { //未结束,指向下一个动画,帧索引归零 fm = framesList[currentAnimationIndex]; nextIndex = fm.framerate > 0 ? 0 : fm.framesList.Count - 1; } } else { //循环,帧索引归零 nextIndex = fm.framerate > 0 ? 0 : fm.framesList.Count - 1; } } //钳制索引 currentFrameIndex = Mathf.Clamp(nextIndex, 0, fm.framesList.Count - 1); //更新图片 RefreshTexture(fm, currentFrameIndex); //设置计时器为当前时间 timer = fm.ignoreTimeScale ? Time.unscaledTime : Time.time; } private void RefreshTexture(FramesAttribute fm, int index) { image.texture = fm.framesList[index]; } public void ManualUpdatePositive() { FramesAttribute fm = framesList[currentAnimationIndex]; DoUpdate(fm); } //反向手动刷新 public void ManualUpdateReverse() { FramesAttribute fm = framesList[currentAnimationIndex]; fm.framerate *= -1; DoUpdate(fm); fm.framerate *= -1; } } public class FramesAttribute { public List framesList; public bool loop; public bool InitialLoop { get { return initialLoop; } set { loop = value; initialLoop = value; } } private bool initialLoop; public event Action OnFinishEvent; public float framerate = 24.0f; public bool ignoreTimeScale = true; public FramesAttribute() { } public FramesAttribute(List _framesList, bool _loop) { framesList = _framesList; InitialLoop = _loop; OnFinishEvent = null; } public void ReSetLoop() { InitialLoop = InitialLoop; } public void OnFinish() { OnFinishEvent?.Invoke(); } } }