Skip to content

Instantly share code, notes, and snippets.

@YogurtTheHorse
Last active July 13, 2021 08:41
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save YogurtTheHorse/c0d982c89c078386e80561d27b2f50e9 to your computer and use it in GitHub Desktop.
Save YogurtTheHorse/c0d982c89c078386e80561d27b2f50e9 to your computer and use it in GitHub Desktop.
using System;
using UnityEngine;
[RequireComponent(typeof(SpriteRenderer))]
public class LineAnimator : MonoBehaviour
{
private SpriteRenderer _renderer;
/// <summary>
/// Флаг обозначающий необходимость проверку смены кадра.
/// </summary>
private bool _revalidate;
/// <summary>
/// Вреия затраченное на нынешний кадр.
/// </summary>
private float _frameTime;
/// <summary>
/// Закэшированное значение номера кадра для проверок необходимости обновлять спрайт.
/// </summary>
private int _oldFrame;
/// <summary>
/// Закэшированная ссылка на старые спрайты для проверок необходимости обновлять спрайт.
/// </summary>
private SpriteLine _oldSprites;
/// <summary>
/// Спрайты для отрисовки.
/// </summary>
public SpriteLine sprites;
/// <summary>
/// нынешний кадр анимации.
/// </summary>
public int animationFrame;
/// <summary>
/// Нужно ли зацикливать анимацию.
/// </summary>
public bool loop;
/// <summary>
/// Включена ли анимация.
/// </summary>
public bool animate;
/// <summary>
/// Время для одного кадра.
/// </summary>
public float frameLength = 1f;
private void Awake()
{
_renderer = GetComponent<SpriteRenderer>();
}
private void Start()
{
SyncSprite();
}
private void OnValidate()
{
_revalidate = true;
}
/// <summary>
/// Время для одного кадра.
/// </summary>
private void LateUpdate()
{
if (animate)
{
_frameTime += Time.deltaTime;
// используем не if, а while на случай, когда фпс меньше чем частота смены кадров
while (_frameTime >= frameLength)
{
NextFrame();
}
}
// Проверяем, что спрайты или кадр поменялись из вне.
_revalidate |= _oldFrame != animationFrame || _oldSprites != sprites;
if (_revalidate)
{
SyncSprite();
}
_oldFrame = animationFrame;
_oldSprites = sprites;
}
private void NextFrame()
{
_frameTime -= frameLength;
if (animationFrame == sprites.sprites.Length - 1)
{
if (loop)
{
animationFrame = 0;
}
else
{
animate = false;
}
}
else
{
animationFrame++;
}
_revalidate = true; // SyncSprite всегда вызывается в апдейте после.
}
/// <summary>
/// выставляем нужный спрайт в спрайт ренедрере. Не вызываем слишком часто, чтобы не дергать апи юнити слишком часто.
/// </summary>
private void SyncSprite()
{
_renderer.sprite = sprites.sprites[animationFrame];
_revalidate = false;
}
}
using System;
using UnityEditor;
namespace Editor
{
[CustomEditor(typeof(LineAnimator))]
public class LineAnimatorInspector : UnityEditor.Editor
{
private SerializedProperty _spritesProperty;
private SerializedProperty _animationFrameProperty;
private SerializedProperty _loopProperty;
private SerializedProperty _frameLengthProperty;
private SerializedProperty _animateProperty;
private void OnEnable()
{
_spritesProperty = serializedObject.FindProperty("sprites");
_animationFrameProperty = serializedObject.FindProperty("animationFrame");
_loopProperty = serializedObject.FindProperty("loop");
_animateProperty = serializedObject.FindProperty("animate");
_frameLengthProperty = serializedObject.FindProperty("frameLength");
}
public override void OnInspectorGUI()
{
var animator = target as LineAnimator;
serializedObject.Update();
EditorGUILayout.PropertyField(_spritesProperty);
if (animator && animator.sprites != null)
{
animator.animationFrame =
EditorGUILayout.IntSlider(animator.animationFrame, 0, animator.sprites.sprites.Length - 1);
}
EditorGUILayout.PropertyField(_loopProperty);
EditorGUILayout.PropertyField(_frameLengthProperty);
EditorGUILayout.PropertyField(_animateProperty);
serializedObject.ApplyModifiedProperties();
}
}
}
using UnityEngine;
public class SpriteLine : ScriptableObject
{
public Sprite[] sprites;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment