[RELEASED] Spritedow Animator, a simple sprite animation system

An easy to use, standalone sprite animation system

Hi everyone!

I’m very glad to announce my first plugin, Spritedow Animator! I make lots of 2D games and the workflow with Mecanim always bothered me, so I decided to make this little plugin in order to enchance my productivity making animations with spritesheets. I use it everyday on my workspace so I’ll improve it with new features, totally free.

I hope you like it and find it as usefull as I do!

ASSET STORE

Spritedow Animator is a simple and standalone alternative to Mecanim to animate sprites frame by frame.

Just drop your sprites or spritesheets to the editor and you will have an awesome animation in a jiffy (hehe).

NOTE
This plugin is oriented to programmers: althought it has a visual animation editor, all the cool features need some code to work.

FEATURES

  • Simple and easy to use Animation editor
  • Animation preview
  • Play animations forward or backward
  • Play random animations
  • Animate ignoring time scale
  • Custom animation framerate
  • Custom frame duration
  • Basic events (onPlay, onStop…)
  • Custom events
  • Works with SpriteRenderer and UI Images
  • Renderer control methods
  • Make simple behaviours without code (loop, random, play on awake…)
  • Completely standalone, this plugin does not use the Unity’s animation system

Changelog

2.0.1
- Fixed a bug with the UI Animator.
- Replaced the UI Animator “Adapt Pivot” property for the new “Preserve Aspect Ratio” property.
2.0.0
VERSION 2.0.0 IS NOT COMPATIBLE WITH PREVIOUS VERSIONS OF SPRITEDOW ANIMATOR.
PLEASE, DON’T UPDATE IF YOU CANNOT AFFORD TO LOSE ALL YOUR ANIMATIONS AND FIX API CHANGES.
- Added actions to the Animation Window
- Added actions to the API
- Improved overall performance
- Improved API
1.2.0
- Added Animation Duration in seconds to the animation API.
- Added “Reverse Frames” to the frames list.
- Improved performance of the animations on low FPS games.
1.1.2
- Fixed a bug where the sprites appear dark on projects with linear color space.
- Improved the synchronization between the Sprite Animation Window and the Sprite Animation inspectors.
1.1.1

  • Fixed a bug with custom events not triggering on frame 0.
  • Fixed a bug with out of bounds index using time instead of frames on the animator.
  • Fixed a bug where the animations would play faster on the editor than ingame.
  • Improved the way the AnimationDuration of the animations is calculated.
  • Added PlayStartingAtNormalized time (without parameter, with animation name and with animation) to the animator API.
  • Added GetFrameTime (with and without FPS specified) to the animation API.
  • Added GetFrameAtNormalizedTime (with and without FPS specified) to the animation API.

1.1.0

  • Fixed a bug with the times of the frames. Now your animations will play FASTER than before, because they were playing SLOWER than desired.
  • Fixed a bug with animations with empty frames on a UI Animator.
  • Added PlayStartingAtTime methods (without parameter, with animation name and with animation) to play your animation starting at the time (in seconds) desired.
  • Added SetAnimationTime method to set the animation’s to the time (in seconds) you want.
  • Added UseAnimatorFPS method to override the animation’s FPS.
  • Added UseAnimationFPS method to go back and use the animation FPS.
  • Added CurrentFrameRate property to get the current frame rate used by the animator.
  • Added CurrentAnimationTime property to get the current animation time in seconds.

1.0.6

  • Added AdaptPivot to the UiImageAnimator
  • Added AnimationDuration to the SpriteAnimation
  • Added PlayStartingAtFrame without animation specified
  • Added PlayStartingAtFrame with SpriteAnimation as a parameter
  • Added AddCustomEvent with SpriteAnimation as a parameter
  • Added AddCustomEventAtEnd without animation specified
  • Added AddCustomEventAtEnd with SpriteAnimation as a parameter
  • Added GetCustomEvent with SpriteAnimation as a parameter
  • Added GetCustomEventAtEnd without animation specified
  • Added GetCustomEventAtEnd with SpriteAnimation as a parameter
  • Added PlayingAnimation proprety that returns the SpriteAnimation currently playing
  • Improved documentation

1.0.5

  • Added Play method with an Animation as parameter to the API.
  • Improved the editor code.
  • Minor bugs solved.

1.0.4

  • Added Fallback animation to the basic behaviours
  • Added Fallback animation type to the basic behaviours
  • Added SetFallbackAnimation to the API
  • Added RemoveFallbackAnimation to the API
  • Added StopAtFrame to the API
  • Solved some minor bugs on the preview window

1.0.3.4

  • Solved a bug with the disable render on finish.

  • Solved some GC allocation with animators without events

1.0.3.3

  • Solved a bug with the PlayOnAwake / OneShot / Backwards configuration.

1.0.3.2

  • Added LoopType to the Basic Behaviours.
  • Added LoopType to the API.
  • Improved Animator Components.
  • Fixed a bug with the panning on the animation window.

1.0.3.1

  • Fixed a bug with the SpriteAnimationAttribute drawer.

1.0.3

  • Fixed some layout errors.
  • Fixed the horizontal panning going backwards.
  • Fixed a false warning showing that the starting frame is out of bounds when the animation only has 1 frame.
  • Added SpriteRenderer to the API.
  • CurrentAnimation returns an empty string if there’s no current animation.
  • Improved the animation creation editor.
  • SpriteAnimation Attribute now refresh correctly.
  • SpriteAnimation Attribute now shows a warning if the animator has no animations.
  • Now the asset created will not be selected on the project view after doing so.
  • Removed the “animationName” field from the Animation. The asset name is now the one used.

1.0.2.2

  • Added PlayStartingAtFrame to the API.

  • Added Panning to the animation preview window.

  • You can reset the animation preview window pressing the “F” key.

1.0.2.1

  • Now the FPS slide saves the value between animations and if the tool is closed.
  • Solved a compilation bug with the animation attribute drawer.

1.0.2

  • Added [SpriteAnimationField] attribute to show animation lists instead of text fields on the editor without custom editors.
  • Added Start At Random Frame to the basic behaviours inspector.
  • Added “FlipSpriteY” to the API.
  • Added “StartAtRandomFrame” to the API.
  • Added “Initialize” to the API.
  • Improved documentation.
  • Solved a bug with very similar animation names not playing correctly.
  • Solved a bug with very short animations not playing the first frame.
  • Minor refactors.
  • Updated readme.

1.0.1.3

  • Added a new example with a simple Platformer.
  • Added the reorderable list to the SpriteAnimation asset. You can now rearrange, add or remove frames of your animations directly form its asset.
  • Added “Current Frame” to the API.
  • Solved a bug with short animations replayed without looping them.
  • Improved the serialization of the editor.
  • Encapsulated some public attributes, now privates.
  • Rearranged some folders.

1.0.1.2

  • Now the frames will be sorted with an AlphaNumeric sort and not with an ASCII value sort.
  • Solved a bug with the last frame of the animation keeping for too long.

1.0.1.1

  • Now the frames will be correctly sorted by name if you drop multiple textures to the drag and drop box.

1.0.1

  • Added disable renderer on finish to the basic behaviours.
  • Added delay between loops to the basic behaviours.
  • Added delay between loops to the API.
  • Improved the frame delete on the frame list of the editor.
  • Fixed a bug that gave a null reference when the last frame of the animation was deleted
  • Fixed a bug that caused the animation not to be selected when it was created.

Game Showcase
(You made a game with Spritedow Animator? Tell me!)

https://www.youtube.com/watch?v=IXUmtziVK9E**__
__
Agatha Knife (Nintendo Switch)**

Agatha Knife (Xbox One)
Agatha Knife (PS4)
https://www.youtube.com/watch?v=uriG_CBgc3E
MechaNika (Nintendo Switch)
MechaNika (Xbox One)
MechaNika (PS4)


Rampage of Technology

Hell Snails

Wrath of Cuteulhu

A Platformer for Ants


Tetratower


Catporters

Hi I recently bought this plugin and have a few questions/issues. I have a hard time importing images for some reason, it takes 3 or 4 tries before the sprites get recognized. When they do import they are out of order, my naming convention is File_A_0000 through FIle_A_0090 etc.

I was also wondering if you could explain how to invoke the sprite into the scene, it outputs a *.asset file I’m not sure where to go from there.

Hi, first of all, thank you for your purchase!

The import issue is weird, I had no problem importing them to the editor with a simple drag and drop to the sprite editor box. I’ll see if it’s some kind of bug. Maybe it’s because they’re separated textures and not a spritesheet. I’ll try to improve that.

As for the order of the sprites, if there are all on the same spritesheet it gets the order correctly, but I’ve seen that it doesn’t works with different textures, I’ll fix that on the next update ASAP.

To start using the animations, you need to create a GameObject on your scene and add the SpriteAnimator component. There you can configure the basic behaviour of the animation (play on awake, looping, etc.) and access the API animation through code.

If you need something more, don’t hesitate to ask!

UPDATE
The sort issue with different textures is now solved and will be in the next update!

I’d love to use this, but I’m having an issue with it where my animations (short, a few frames), get hung up on the last frame before looping back to the beginning. I have all the delay variables turned off / max delay set to zero. This only hapens in game, and not in the preview window.

This is a cool solution you’ve built otherwise.

Hi killradius!

Thanks for your feedback, that must be some kind of bug and need a solution ASAP. I’ll keep you informed, it will be solved on the next update for sure!!!

UPDATE
It was a bug indeed. I solved it and the submission to the asset store is pending review now. I hope this solves all your problems, sorry for the inconvenience!!

This update includes also a change on the algorithm sorting the sprites by name in order to make it alphanumeric :slight_smile:

Cheers!!

@Elendow Could I get a video or more documentation on how the scripting part of the plugin works, so I can better understand what is included in the package?

Hi @Ben-BearFish

Yes, I’ll prepare a video and upload this weekend with some examples of code. The package includes a scene with an example of the event system usage, but I can post it here without problem:

using UnityEngine;
using Elendow.SpritedowAnimator;

public class EventExample : MonoBehaviour
{
    private SpriteAnimator spriteAnimator;
    private ParticleSystem particles;

    private void Awake()
    {
        particles = GetComponentInChildren<ParticleSystem>();

        // Here we add an event to the 9th frame of the animation Slimedow
        // After that, we subscribe the method "BurstParticles"
        // We can also get the event with spriteAnimator.GetCustomEvent("Slimedow", 9) and suscribe whatever we want
        spriteAnimator = GetComponent<SpriteAnimator>();
        spriteAnimator.AddCustomEvent("Slimedow", 9).AddListener(BurstParticles);

        // Then we simply play the animation and the magic begins
        spriteAnimator.Play(false);
    }

    private void BurstParticles(BaseAnimator caller)
    {
        particles.Play();
    }
}

In this code, I play an animation looped (Play(false)) and suscribe the BurstParticles to the 9th frame. So, every time the animation plays the 9th frame the BurstParticles will be called.

As I said, I’ll try to record more usage examples on a video this weekend, hope this helps in the meantime :slight_smile:

Cheers!

Do you know if we can set the events in the editor inspector?

Hi again,

It’s not possible at the moment. I’m looking for a way to do it, it’s on the roadmap but I don’t know when I could push it to the Asset Store. Sorry for that.

Cheers :slight_smile:

I made a new example where you can see simple calls to the asset API. It’s a simple platformer using things like “Play”, “CurrentAnimation”, “FlipSpriteX”…

The example will be included in the next version with some improvements and I recorded everything, so, you have a video in the first post with the process.

Hope this helps!

Hi Elendow. I recently purchased your asset and wanted to give you some feedback about it. Overall it seems nice and simple and I don’t want to take away from that because that’s a very strong point. However, there are a few issues that I wanted to comment on.

  1. Proprietary animation format. I was really really hoping this would use Unity’s built in animation clips since that’s what all of my tools (and most everyone else’s) work with. I’ve had to shelve using this asset within minutes of purchasing it because of that (though I will like use it for my next project since I won’t be so invested in animations that already exist).

  2. Strings for animation names? You really ought to be using a string-to-hash system. It allows for users to enter human-friendly strings that get converted into ints internally. This will cut down on runtime allocations significantly if you’re using a lot of sprites. Though it’s not hard to write one yourself I recently discovered that Unity actually has one already. Simply using the type PropertyName instead of strings for your animation names will make it a relatively simple process. Keep in mind this will likely break pre-existing projects if user upgrade.

Anyway, thanks for this contribution to the asset store!

1 Like

Hi Sluggy!

Thanks a lot for your feedback, it really means a lot to me and it’s the best way to improve this asset :slight_smile:

Well, point by point ^^

  1. Thats true, my target with this plugin was exactly that, I always tought that the unity animation system was too complex for simple sprite animations. If you want an animation window using the unity animation system you could try this plugin https://www.assetstore.unity3d.com/#!/content/71177?aid=1101lIr6 that is basically a reskin for the animation window oriented to sprites.

  2. Yes, that’s something that I always wanted to change, but I didn’t because of what you said, it will break the pre-existing projects. I’m looking for a mid-term solution that improves this and doesn’t break the previous projects.

I keep working on this asset to improve it, if I can solve this issues, I’ll get in touch with you :slight_smile:

Cheers!

You might have misunderstood me here so I just wanted to clarify: I meant that it would have been nice to use Unity’s animation clips in a animator that isn’t mecanim. But I won’t argue the point since there are quite a few hurdles to jump through to get such a thing working and most folks just use mechanim as a backend anyway. Anyway, thanks for the response and keep up the good work.

P.S. Wanted to point out that I did end up using this for some smaller parts in my current project. It’s quite refreshing to simply be able to churn out a script in two minutes that just plays an animation. :smile:

Oh, I understand now, I never really thought in that, I’ll check if I can do something with that :slight_smile:

I’m really happy that you’ve been able to enjoy the plugin, I’m actually using it the same way in my current work, for FX and stuff like that.

Thanks a lot for your feedback, it really makes me happy to see that someone is using this asset and finds it usefull :slight_smile:

Hi!
I thought i might share a little script I wrote for SpriteDow:

I have a lot of objects that use the same animations with the exact frame count and timing but of course with different sprites. It became quite annoying to copy the animations and replace each frame manually. So I wrote a script that allows you to replace frames of multiple animations, as long as the sprites of the animations you want to replace are all located in the same folder.

Example:
Old Frames:
[OLDsprites\jumpAnimation.asset]
OLDsprites\jump1.png
OLDsprites\jump2.png

[OLDsprites\shootAnimation.asset]
OLDsprites\shoot1.png
OLDsprites\shoot2.png

Replaced Frames:
[NEWsprites\jumpAnimation.asset]
NEWsprites\jump1.png
NEWsprites\jump2.png

[NEWsprites\shootAnimation.asset]
NEWsprites\shoot1.png
NEWsprites\shoot2.png

All you have to do is to add the script to a empty game object, make a copy of all animations you want to replace to another folder (or in whatever way you organize your animations) and put all animations you want to replace into the list of the script.

Now open the context menu of the script (the small gear in the upper corner of the script in the inspector window) and select “Replace Frames”. The context option “Get current image path” allows you to get the sprite path of the current animations, so its easier to replace animations which share the same root path.

I recommend to make a few test to get how it works. I doubt it can harm your animations in anyway, the only thing that might happen afaik is that you have a mixture of new and old frames IF you didn’t use the script in the correct way.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Elendow.SpritedowAnimator;

#if UNITY_EDITOR
using UnityEditor;
#endif

public class cs_spriteDowAnimationTool : MonoBehaviour
{
#if UNITY_EDITOR
    [Header("All frames in all animations present in the list have to share the same folder")]
    public List<SpriteAnimation> anim;
    [Header("Source Image Path")]
    public string imagePath;

    [ContextMenu("Get current image path")]
    public void getInfoFromCurrentAnimation()
    {
        if (anim.Count > 0)
        {
            if (anim[0].Frames.Count > 0)
            {
                imagePath = AssetDatabase.GetAssetPath(anim[0].Frames[0]);
                imagePath = imagePath.Replace(anim[0].Frames[0].name + ".png", "");
            }
            else
            {
                Debug.Log("No Frames found");
            }
        }
        else
        {
            Debug.Log("No Animations found");
        }
    }
    [ContextMenu("Replace Frames")]
    public void replaceInfoFromCurrentAnimation()
    {
        if (anim.Count > 0)
        {
            foreach (var dowAnims in anim)
            {
                if (dowAnims.Frames.Count > 0)
                {
                    if (imagePath != "")
                    {
                        for (int i = 0; i < dowAnims.Frames.Count; i++)
                        {
                            if (AssetDatabase.LoadAssetAtPath(imagePath + dowAnims.Frames[i].name + ".png", typeof(Sprite)) as Sprite)
                            {
                                Sprite newFrame = AssetDatabase.LoadAssetAtPath(imagePath + dowAnims.Frames[i].name + ".png", typeof(Sprite)) as Sprite;
                                dowAnims.Frames[i] = newFrame;
                            }
                            else
                            {
                                Debug.Log("Image Name/Folder >>>" + imagePath + dowAnims.Frames[i].name + ".png" + "<<< is not the same/not present");
                            }
                        }

                    }
                    else
                    {
                        Debug.Log("No image Path set");
                    }
                }
                else
                {
                    Debug.Log("No Frames present");
                }
            }
        }
        else
        {
            Debug.Log("No Animator Source selected");
        }
    }
#endif
}
1 Like

Woah, nice one @Crystian!

Never tought that someone would need that, but this trick is really cool. You could improve it using an EditorWindow, that way you don’t need a GameObject on the scene to execute your code.

I’m glad you’re using the asset and improving it, it’s really cool, seriously.

Cheers!

2 Likes

Can this play multiple animations at the same time? I mean I have a multisprite character (head, body, weapon) and I would like to play those 3 animations at the same then for example replace the sword animation for the axe animation.

I just realized this doesnt make much sense since this works with one sprite renderer so I would need to use 3 different components one for each.

Yeah, that’s exactly what I was gonna tell you. BUT, I could make a “PlayAnimationFromFrame”. That way you could play the axe animation starting where the sword animation was.

Tell me if that could be useful to you and I’ll try to add in the next update :slight_smile: