RTF DevLog: Unity Struggles and Custom Animator



As promised, here is a little tech talk. This talk is about the peculiarities of Unity and how we deal with them.

For me, it's the first project on Unity and the second one for my partner. If you come from a more modern engine and use Unity for the first time, you will notice how user-unfriendly and overly complex it is in many places and still doesn't support many use cases. You recognize the basic idea of how something should work but often shake your head in disbelief at how poorly it is implemented. It is also no wonder that the Unity asset store is full of alternative implementations with things that one would actually expect from the engine.

Using the animation system in Unity as an example, to have a look at our everyday problems. The system probably works quite well for 3D, but it is quite unsuitable for our 2D use case with many sprites that are also exchanged. This is mainly because it is not the sprite renderer that is animated, but the loaded sprite. However, since we have a lot of individual sprites in our game for e.g. the different types of trousers, shirts, weapons and haircuts, we would have to animate each individual sprite sheet with the animation system. If the timing of an animation changes, we have to adjust it everywhere. 

Animation in Unity

Animation in Unity

This is much better implemented in Godot, for example. There the Sprite2D object is animated, to be more precise the property "frame" (for a sprite sheet). You can simply change the texture in the code. E.g. leather trousers to military trousers. This way the animations remain small and manageable. Another problem was that the timings of the animations always felt a little off compared to Aseprite.

Our character in Aseprite showing only some of the many layers

After asking around on Reddit and Discord, we came to the conclusion that it's best to write your own animator. Or take a solution from the asset store. So we started to think about what such an animator should be able to do and came to the conclusion that the following features would be great for our use case:

1. it should be possible to change sprites (change of clothes)

2. parse animations directly from Aseprite and adjust them manually later, if necessary, instead of creating everything manually.

3. suitable for multiplayer

4. support for callback functions and loopable 

In the first prototype we tested whether it is at all possible to change the sprite of a sprite renderer by code or whether the renderer is designed in such a way that it is generally not possible to reload sprites. To our great relief, this works and we can now not only reload sprites for animation if needed, but also provide different skins for the GUI.

The parsing of the Aseprite file was done outside of Unity with Node, because we didn't want to have it as productive code, nor did we want to do the work of writing a plugin for Unity. The code can be found here in this gist. This code looks for given animations in Aseprite and export it as multiple files including the timings and indexes.

To make the animation system suitable for multiplayer, we also need information on when the animation starts. That's why we need to be able to start or synchronize animations with an offset.

In our test implementation, we ended up with only three public functions:

// Play the given animation
public bool Play(string animation_name, float offset = 0.0f);
// Load a sprite into the given objectIndex (SpriteRenderer reference)
public void LoadSprites(byte objectIndex, string texture_name);
// Clear a sprite from given objectIndex - e.g. drop shirt
public void ClearSprites(byte objectIndex);

The whole dummy implementation can be found in this gist. Note that this isn't the actual production code, we've made further improvements like syncing and making it more robust.

Sample animation in aseprite

Sample animation in aseprite

Thanks for reading and we hope you'll check back next time. In the meantime, we'd love for you to like and share this post if you enjoyed it. Also, we are now on Steam and you can wishlist our game: Steam Web or steam://store/2585860

Leave a comment

Log in with itch.io to leave a comment.