How to manage 2D animation states (of same behaviour) for multiple type of characters/enemies?

Hi all, I am a newbie to Unity,
would like to know how is this situation normally handled in Unity:

The scenario:

My game (2D) has got 50 types of enemies with some generic behaviors and animation states:

  • standing : animation state idle
  • walking : animation state walk
  • attack : animation state attack … and so on

[My old method]

I was previously making game on GM:S. I normally do it like following:
Firstly create sprite for each states for all enemies respectively, and named them accordingly while importing to asset library.
For instance:

  • spr_enemy1_idle,
  • spr_enemy1_walk,
  • spr_enemy1_attack,
  • spr_enemy2_idle,
  • spr_enemy2_walk,
  • spr_enemy2_attack…and so on.

Then i will have a parent object for generic enemy behavior,
that will store the ‘enemy name’ and ‘state name’.
When i tell certain enemy instance on stage to perform an action, it will look for the ‘enemy name’ and ‘state name’, then look through the asset library and bring up the animation sprite (animation state) accordingly.

for example:
when instance of enemy1 were to perform an attack action, the script will look for asset with name “spr_”+“enemy1”+“_”+“attack”, get the sprite, and set the current sprite_index (or animation state in unity) accordingly.

in short, i import all my sprites, name them accordingly, and script the generic rules how the animation state works. Then when i create an enemy instance on scene, i just need to define the enemy name (eg. “enemy1”, “enemy2”) for it to work accordingly. If i need to further customize certain behavior, i can create a cub-class from there.

*note: The look up on the asset name can be done once when the instance initiated and stored in a reference variable, so that it won’t be looking through the asset library every time when the animation state changed.


[in Unity]

From what i have learned so far. User normally create animator controller(for each enemy) and animation states (for each states of respective enemies) then link them in animator controller accordingly.

When i was following the 2D Roguelike tutorial, it uses ‘Animator Override Controller’ to define animation state for Enemy2 which have similar behavior as Enemy1. Which is quite handy, but still, when i have 50 or more enemies, i still have to manually create another 49 ‘Animator Override Controller’ then drag in corresponding animation states in to the component to override the states. I think this is rather repetitive and hard to manage. If i later decided i need to add a new state (eg: “jump”), i will have to go through the process 49 times again…

How is such situation normally handled in Unity?

Thank you :slight_smile:

i still have to manually create
another 49 ‘Animator Override
Controller’ then drag in corresponding
animation states in to the component
to override the states. I think this
is rather repetitive and hard to
manage. If i later decided i need to
add a new state (eg: “jump”), i will
have to go through the process 49
times again…

That is Unity for you… lots of time consuming, repetitive work.

Unity’s animation system is IMO, pretty lacking. It’s designed for very specific animation styles, like Don’t Starve or Darkest Dungeon style 2D animation. You’ll find a lot of problems (inefficiency) using it for anything outside of this intended purpose, like pixel art or SNES style sprite sheets.

It is a system which works much better without the need to change sprites ever single frame.

Alt text

So unless you’re doing this style, you probably won’t find the Unity Animation System all that efficient.

How is such situation normally handled
in Unity?

Most developers probably just do this repetitive work by hand. That’s a very inefficient way, and you are entirely correct to want to avoid this pointless work. However Unity isn’t the best tool in cases like this; in fact, it’s downright horrible.

Smarter developers would handle it this way:

  • Automate the process. Write an (editor) script to automatically create these Animators/Animations & set them correctly based on naming conventions in the sprite.
  • Replace Unity’s Animation System with your own, which is based on naming conventions in the sprites. (Like you did in your old method). This is what I would suggest.

Be sure to also automate the naming process, by using an app like Flash Renamer or something similar. It is a PITA to rename things by hand, just like it is to create the same animator/animations 49 times in a row. Bleh.

If for whatever reason you feel the need to retain some usage of the Unity Animator/Animation System, you can

  • Create an animation script exclusively for use in your Animations
  • Create a single animator & animations for all characters (assuming they all share the same animations)
  • Use Animation Events to do interesting stuff, change sprites, track the current animation, or whatever.

I use this method to link Animations with game logic (character actions from input). I use Unity’s Animation System to very simply have a set time that an action takes to complete, such as harvesting grass. When the animation is complete, it calls an event. The actual animation is unnecessary. (You’ll want to make sure your transitions have Exit Time of 1 & transition duration of 0, or else they can skip these animation events.) It’s a quirky way to use the animation system, but it works.

Not sure if you’d even want to do this if you had your own system, but I figured I’d mention this in case, for some reason, you found it efficient to maintain usage of Unity’s animation system.

using UnityEngine;
using System.Collections;

public class AnimationEventCommands : MonoBehaviour
{
    public void MyParent_PlayerCharacter_StopPerformingAction()
    {
        this.transform.parent.parent.GetComponent<PlayerCharacterInput>().isPerformingAction = false;
    }

   public void ChangeAnimation(string animationName)
   {
       this.transform.parent.parent.GetComponent<CharacterAnimationManager>().SetAnimation(animationName);
   }

    public void Self_ColorMeRed()
    {
        //sprite.color = red;
    }

    public void Self_SelfDestroy()
    {
        Destroy(this.gameObject);
    }