Unity3D的2D幀動畫控制工具編寫
阿新 • • 發佈:2019-01-08
前些日子公司讓筆者寫了一個幀動畫控制工具,主要是用來控制聊天表情這些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(); } }