using UnityEngine.UI; using UnityEngine; #if UNITY_EDITOR using UnityEditor; #endif [ExecuteAlways] public class FrameAnimator : MonoBehaviour { public Sprite[] sprites; public float frameRate = 10f; public bool preview; public bool isPlaying = false; public bool loop = true; public int currentFrame = 0; float m_frameTimer = 0f; bool m_previewPlaying = false; #if UNITY_EDITOR double m_lastEditorTime = 0d; #endif Image m_img; Image img { get{ if(m_img==null){ m_img= GetComponent(); } return m_img; } } void OnValidate() { if(preview) { preview=false; StartPreviewOnce(); } } void OnEnable() { #if UNITY_EDITOR if (!Application.isPlaying) { m_lastEditorTime = EditorApplication.timeSinceStartup; EditorApplication.update -= OnEditorUpdate; EditorApplication.update += OnEditorUpdate; } #endif } void OnDisable() { #if UNITY_EDITOR EditorApplication.update -= OnEditorUpdate; #endif } void Start() { if (sprites == null || sprites.Length == 0) { return; } currentFrame = Mathf.Clamp(currentFrame, 0, sprites.Length - 1); ApplyCurrentFrame(); } // Update is called once per frame void Update() { if (!Application.isPlaying) { return; } TickAnimation(Time.deltaTime); } #if UNITY_EDITOR void OnEditorUpdate() { if (Application.isPlaying || this == null || !isActiveAndEnabled) { return; } double now = EditorApplication.timeSinceStartup; float dt = (float)(now - m_lastEditorTime); m_lastEditorTime = now; if (dt <= 0f) { return; } TickAnimation(dt); EditorApplication.QueuePlayerLoopUpdate(); } #endif void TickAnimation(float deltaTime) { if (frameRate <= 0f || sprites == null || sprites.Length == 0) { return; } bool shouldAnimate = m_previewPlaying || isPlaying; if (!shouldAnimate) { return; } m_frameTimer += deltaTime; float frameDuration = 1f / frameRate; while (m_frameTimer >= frameDuration) { m_frameTimer -= frameDuration; if (m_previewPlaying) { AdvancePreviewFrame(); } else { AdvanceFrame(); } } } public void Play(bool restart = false) { if (sprites == null || sprites.Length == 0) { return; } if (restart) { currentFrame = 0; m_frameTimer = 0f; ApplyCurrentFrame(); } isPlaying = true; } public void Stop() { isPlaying = false; m_frameTimer = 0f; } public void ResetToFirstFrame() { currentFrame = 0; m_frameTimer = 0f; ApplyCurrentFrame(); } void StartPreviewOnce() { if (sprites == null || sprites.Length == 0) { return; } isPlaying = false; m_previewPlaying = true; m_frameTimer = 0f; currentFrame = 0; ApplyCurrentFrame(); } void AdvancePreviewFrame() { currentFrame++; if (currentFrame >= sprites.Length) { currentFrame = sprites.Length - 1; m_previewPlaying = false; } ApplyCurrentFrame(); } void AdvanceFrame() { currentFrame++; if (currentFrame >= sprites.Length) { if (loop) { currentFrame = 0; } else { currentFrame = sprites.Length - 1; isPlaying = false; } } ApplyCurrentFrame(); } void ApplyCurrentFrame() { if (img == null || sprites == null || sprites.Length == 0) { return; } currentFrame = Mathf.Clamp(currentFrame, 0, sprites.Length - 1); img.sprite = sprites[currentFrame]; } }