Search Unity

Single animation, multiple sprite sheets?

Discussion in '2D' started by migueltuliompg, Aug 15, 2019.

  1. migueltuliompg

    migueltuliompg

    Joined:
    Feb 12, 2018
    Posts:
    63
    Hello once again all!

    Has anyone come up with a good solution for interchanging sprite sheets with one animation? By that I mean being able to have multiple skins for the same animation.

    I found one solution that use Resources.load to load the correct sprite in late update, but that seems unnecessarily CPU intensive. Is there really no other solution for this?

    If anyone has any ideas I would love to hear them!

    Edit: I'm am planning on having animations that move the body parts and change their sprites (like hand open, hand closed)
     
  2. Hyblademin

    Hyblademin

    Joined:
    Oct 14, 2013
    Posts:
    725
    If I'm understanding correctly, you want to use a single set of animations-- I'm guessing one Animator controller-- to control what is presented in-game as a cast of characters. Behind the scenes, though, it's really a single configurable actor which can have skins assigned to look like different characters (behaviors are another subject).

    When using puppet animation, this is no different from assigning different 3D model files to the same 3D animation data. In this case, it can be done as long as the models all follow similar rigging schemes. In your case, all you need to do is make sure that all of the same body parts are available and are referenced in the same way.

    I think you might already understand that, though. If you're asking about the most performance-optimized way to actually do this, then it depends on what you want to optimize and under what circumstances in your game the skins will be changed. Some things I'm wondering about for your project:

    -Should skins be allowed to be dynamically swapped during a game? Are they only selected ahead of time, as part of a character select screen or similar UI?

    -What's the target platform? Are you most concerned about CPU overhead, memory consumption, storage space?

    -How many textures are needed for a single skin? Roughly how much sheet space is needed to pack one skin?

    -How many skins are you expecting?


    If you only allow skins to be pre-selected before a game session, then loading sprites on-the-fly is a reasonable approach if there are a large number of skins to choose from. If there are only a handful, loading them all ahead of time then just reconfiguring the renderers when needed should be fine.

    If skins can be swapped at any time, like by using a game item or selecting from an live-game UI, then it would probably be a similar situation, but might be more concerned with how many skins are available to the player at a given time. For example, if there is some kind of inventory item used to change costumes or equipment, you could asynchronously load the textures for the item when they are acquired or otherwise chosen by the player to be available (like withdrawing from an item box or bank), and unloaded when they are lost or put away.

    Hopefully I'm at least on the right track to getting at what you're asking for.
     
  3. migueltuliompg

    migueltuliompg

    Joined:
    Feb 12, 2018
    Posts:
    63
    Thanks for the reply!

    Right before reading this, I figured out a solution that loads the sprite sheets as dictionaries, and then after the animator runs, the script gets the correct sprite from the dictionary with the name of the sprite the animator switched to!

    Like this, but mine loads them ahead of time and has multiple sprite renderers https://www.erikmoberg.net/article/unity3d-replace-sprite-programmatically-in-animation

    Thanks!
     
    AzUnity and pasibogrichavit like this.
  4. bitdena

    bitdena

    Joined:
    Jun 24, 2020
    Posts:
    1
    I have been looking for an answer to this problem recently. I have found a very similar solution, however simpler, using Sprite Atlas, so I though I might share it here:

    Build your animations as regular, using any sprite set.
    Create an sprite atlas (Right Click -> Create -> 2D -> Sprite Atlas), drag and drop your sprite sheet in "Objects for Packing" field of the Sprite Atlas, set its settings the same way your sprite sheet is set.
    Now in the object that renders the sprites, create an script similar to the following one.

    Code (CSharp):
    1.  
    2. using UnityEngine;
    3. using UnityEngine.U2D;
    4. public class CharacterAnimator : MonoBehaviour
    5. {
    6.     private SpriteRenderer spriteRenderer;
    7.     private bool updateSprite = false;
    8.     [SerializeField] private SpriteAtlas spriteSheet;
    9.  
    10.     private void Awake()
    11.     {
    12.         if(spriteSheet != null)
    13.         {
    14.             spriteRenderer = GetComponent<SpriteRenderer>();
    15.             updateSprite = true;
    16.         }
    17.     }
    18.  
    19.     //LateUpdate changes the shown sprite if a spritesheet is used.
    20.     //The spritesheet (sprite Atlas) must have an sprite with the same name.
    21.     private void LateUpdate()
    22.     {
    23.         if(updateSprite)
    24.         {
    25.             string spriteName = spriteRenderer.sprite.name;
    26.             spriteRenderer.sprite = spriteSheet.GetSprite(spriteName);
    27.         }
    28.     }
    29. }
    The logic is very simple, if your object has an Sprite Atlas, in the late update it will switch the original sprite in the Animation Clip for one with the same name in the Sprite Atlas.
    From here on, in order to swap the animated sprites you would just need to drag and drop an new Sprite Atlas with the new sprites and make sure that every single sprite has the same name as the one it should substitute in the original Sprite Sheet.
     
    vaybefree likes this.