Unity animations are a nightmare for spritesheets


So after working in projects in the past, especially for 2D sprite animation. I've always just make my own animation handler script. Basically it would just iterate over sprites with a delay between each in seconds, using deltaTime. But after working on a project where someone deleted all my animations in favor of the animation system in Unity, I thought this time I'll do it "properly" and use the built-in Unity animation system for this game jam and hopefully save some time! 

It took a while to understand how it works, for example you need about 3 windows open to manage the library (you need to be able to click on the animations in the folder to turn the loop on and off), the "Animation" tab - with the keyframes, and then the "Animator" tab with the state and transitions node-based editor.

While I understand the animator is great when you have a 3D character and want to do morphs between each animation and link them to scriptable variables... I quickly discovered that when all you need to do is animate a few 2 to 3-frame explosions and muzzle flashes it's the biggest more tedious pain in the ass. So here are the big pains I discovered:

  1. You first have to turn on all the windows that you will need, which take up the entire screen. As stated in the intro, you need the "Animation" tab - with the keyframes, the "Animator" tab - with the state and transitions, and the "Project" tab - where your prefabs, animations, sprites, textures, and animation controllers (states and transitions) are kept. You need to be able to click on an animation after you've saved it to uncheck the "Loop Time" option because you can't get to it from the "Animation" tab. 

  2. Next you have to make sure your prefab has a sprite as a child to the actual object - because if you decide to animate the sprite directly, good luck trying to move it around the screen because if you need to change the transform during the animation at all, it will lock in place and the animator will completely take over - which makes sense if you think about it, but the annoying thing is, if you accidentally NOT do this, you have to re-do the animation from scratch, because there's no way of MOVING the animation from one object to another, you do this and the Sprite that the animator is trying to change is "Missing".
  3. You click the Create button and it intrusively opens a File Save Dialogue box. This usually opens in whatever folder you currently have open in your Project tab, so if you have a bunch of prefabs you're trying to animate, and you click this Create button, it will open the Prefabs folder and you have to navigate back, go to the Animations folder (assuming you have it set up like that, but if you have all your Prefabs and Animations and whatever else in 1 folder then you probably have bigger problems...) every single time. Even if you save an animation in the folder and click Create again, it just opens the Prefabs folder again, so for every animation you have to go through this save dialogue back open process and just for creating an animation, all while it creates an entire file for each.
  4. You then have to choose a name for your animation. And if you make a typo? Good job, now your AnimatorState is named wrong and you also have to go into the animation (by clicking on it in the Project browser tab), open the "Animator" tab (not the "Animation" tab, that's wrong sorry) and find that state (mostly there's 1 but sometimes the state position in the generated node graph is in a really odd place so you have to zoom out, other times they stack diagonally down right and there's no way to search for them)

    and find the one that's wrong and make sure you fix the typo there too. This is important because if you're trying to script an AnimationState to start and it was changed ever, you'll be wondering why it's not playing, and also WHICH object (if you have the same script on multiple objects like different enemies) is throwing the "missing state" error. You double-click the error message, it opens the script that is throwing the error, and it has animator.Play(stats.muzzleFlashAnimationName, -1, 0f); so what state am I looking for? I need to put a debug log and figure that out before I can even start looking for this state.
  5. Even if there are multiple sprites that have the exact same animation eg. a 3-frame ping-pong style animation that has 0.05 seconds between each frame, you have to create an entirely new animation for this. There's no way to share an animation timeline but have it have a different set of sprites. This is good for being flexible, but if you're in a game jam and you're trying to save time, this is not cool, especially for all my 2 frame muzzle flashes which are all exactly the same, but they instead all have their own animation file!
  6. It sometimes creates an "AnimationController", but not always. It seems to be if a prefab or any object doesn't have any animations on it yet, it automatically creates one with the "name" of the GameObject automatically, so make sure you have your GameObjects in the Hierarchy and in the Prefab viewer or you'll have an AnimationControllers called "Bullets 1_8" and can't change it. because the animation that also got created alongside this file will be "missing" and you'll need to do the animation again.
  7. Getting the timing right is a pain in the ass. When you create a new animation, it will start the Animation tab in a zoomed out state and this will be a different zoom for every animation, because by default it will try and fit the fill animation in the width of the panel. Convenient? No, because then you lose all comparisons of how often each frame changes until you look at the seconds and are like "Okay the second frame should be 2 frames before 0.05 but only in 60FPS, in 30FPS that would only be 1 frame before the 0.05 mark, I have it written down on a piece of paper!"
  8. Speaking of frames, if you need to move a sprite for just 1 frame, it defaults to tween the animation, and not from the previous frame - from the FIRST frame. To do a correct sprite animation which has X, Y  changes, you have to first move it a tiny bit while the first frame is selected, copy that frame, move it to 1 frame before the one you want to change position on, and then change the position on that frame. Why? Because you can't move it and then undo, that will remove the keyframe. You can''t just "Add keyframe" because it won't know what you are adding the keyframe to, in my case it was a keyframe for the "sprite change", which is not what I want, I need a keyframe for transform. To do this you would need to go to the "Curves" view inside the Animation tab and add the keyframe there, and then right click the keyframe and set it to "Flat" curve, and then fiddle with it until it isn't moving smoothly between the 1 frame. 

    The zoom inside the curves view does both X and Y so if you have something that's way off centre on 1 of these exes and need to tweak the curves in the timeline subtly, it makes it hard to see everything going on. The maximum you can have is 60fps as the reference, so you can't cheat and just ignore the tween between those frames because on computers with higher than 60FPS, you'll see the sprite move during the frame change which breaks the sprite-sheet feel.
  9. Speaking of FPS, yes, the final annoying thing is that the sample rate has 24, 25, 30, 50, and 60 FPS options.

    There are none for 10, or 12 FPS which is the speed I did my animations in Flash before exporting them, so you have to have the sprite change at minimum every 2 frames, which makes it annoying when the thing starts zoomed out and you have to double-check where each keyframe is and the timing of each. I basically just left them all at 60 FPS because I got tired of changing them all the 24 FPS and setting every second frame because if I needed one of those copy-pasted position frames there, it's harder to see if it's an actual frame change or a preparation for a frame change - they are all just next to each other. With 60 FPS it's also easier to cheat with the curves and not go in to make them "flat", on 24 FPS there's more time between frames so the awkward tweening is obvious. My game is for mobiles mainly, so I set the "Target FPS" to 60 (side note, did you know Android builds automatically cap the frame rate to 30 by default to help save battery life?) and you can't see the tween at all. This isn't to say it's not painful to have to do all the gymnastics to get this outcome though.

One exception to this could be a character walking cycle if you want to control the animation via script to say which direction they are facing. 

But if you need to animate lots of 2D sprites like bullets or looping objects and maybe transform tweaks (scale them and change colours over time), then make your own script for it for the love of god. It could be 1 or 2 functions with about 6 lines of actual code compared to hours of clicking and boxing through all these animation systems that were built for 3D character animation, and not for simple transitions.

I hope you learned something about the animation system at least and if you've also experienced this pain (anyone that's done pixel-art sprites, I'm thinking of you) chuck a like on this post.

Good luck on your game jams and big games you lovely people.

Leave a comment

Log in with itch.io to leave a comment.