Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Multiple Sprite Renderers with one Mecanim animator possible?

Discussion in '2D' started by Eyeshock, Dec 18, 2016.

  1. Eyeshock

    Eyeshock

    Joined:
    Sep 7, 2012
    Posts:
    60
    Hello,

    I'm doing something quite common: adding customizable equipment to 2D sprites via layering sprites. I've searched long as hard for a solution to what I thought would be a very simple implementation, but to no avail.

    A) I have multiple sprites that play simultaneously to create the illusion of armor and weapons on my body model.
    B) Currently, I'm being forced to use multiple animators, one for each layer; this isn't sustainable since everytime I change one state machine, I'd have to duplicate.

    What I've tried....
    1) I tried Base Layers. This is obviously not meant for 2D as the highest weight sprite just plays solo (even with additive, blending turned on)

    2) I've tried putting the Animator on a parent object and adding multiple sprite renders to children, one for each layer; then I tried setting the animations to run on independent renderers in the animation view. I honestly couldn't figure out how to make it work nor find a tutorial or reference.

    Things I've considered...
    1) Build a custom animation machine via code; but I'm just pickng up unity years after Mecanim was implemented, and I'm worried coded engines and legacy animation systems are being phased out?

    2) Maybe use a single mecanim engine then run behavioral scripts based on tree from each state. Then hard code the animations to run on each layer's sprite renderer from the behavioral scripts.

    Anyway, I'm certain this has to have been done and addressed a million times, but I just can't find a solution; and most the solutions I do find say use base layers, but that doesn't seem to do the trick.

    Any help would be awesome. Thanks in advance!
     
  2. piggybank1974

    piggybank1974

    Joined:
    Dec 15, 2015
    Posts:
    621
    Have you got any visuals for this I'm having a hard time seeing what your trying to do.

    I would of though you going overboard but without more info I'm not sure.
     
  3. Eyeshock

    Eyeshock

    Joined:
    Sep 7, 2012
    Posts:
    60
    Hey! Sure thing.

    Basically, I want to build sprites in Aseprite, then output a layer for the MODEL, WEAPON, SHIELD, ARMOR, etc. and recombine them depending on the gear the player is using.

    Here's a quick example:

    Here's the layers separated:


    And here they are combined using multiple animators (but again, the biggest problem with this is I'm duplicating animators and that's just not sustainable)
     
  4. piggybank1974

    piggybank1974

    Joined:
    Dec 15, 2015
    Posts:
    621
    I see looks cool, anyways, you can have loads of animations, I suspect that you will or could have hundreds because of your different weapons, this might be the only way to go on this I'm not to sure about subjecting anything else, mecanim is ok, I wonder what about a branch group in mecanim, I cannot remember what it's called.
     
  5. Sluggy

    Sluggy

    Joined:
    Nov 27, 2012
    Posts:
    843
    This can be done but it is a real pita. It's been a while but I think I had a single Animator on a root GameObject and then had several child objects with sprite renderers on each. when working in the animation dope sheet I had to hit the record button and change each child sprite once. After that, the property for each child's sprite would appear in the dope sheet and I could animate all of them in one go. I only had a handfull of different child sprites to do this way so it wasn't tereible but if you have a lot you'll certainly want to automate some of this with editor scripts.
     
  6. Eyeshock

    Eyeshock

    Joined:
    Sep 7, 2012
    Posts:
    60
    So I think I found a solution and I'm posting it here for anyone who may search for it in the future. I'd also like some feedback in case I'm setting myself up for a disaster in the future.

    I use a single Animator with Blank Animations all named after the state; Idle, Run, Etc. I assign the animator to a gameobject, one for each layer of animation (Weapon, Body Model, Offhand, Etc.)

    I use AnimatorOverrideController to change the animations for each animator; the code I used it below.
    Code (csharp):
    1.   private void LoadAnimationLayers (Animator anim, int animSetID) {
    2.  Debug.LogWarning ("LoadingAnimationLayers");
    3.  RuntimeAnimatorController myController = anim.runtimeAnimatorController;
    4.  AnimatorOverrideController myOverrideController = new AnimatorOverrideController();
    5.  myOverrideController.runtimeAnimatorController = myController;
    6.  //AnimationnewAnimation=Resources.Load("Animations/GirlIdle");
    7.  Debug.LogWarning ("Animation:" + myOverrideController["BoyIdle"]);
    8.  
    9. // TSMaster.animDB is a static attribute that refers to a gameobject with AnimatonDatabase as a List of Clips
    10.  myOverrideController["_Idle"] = TSMaster.animDB.animSetCollection[animSetID].animSet[0];
    11.  //myOverrideController["_Walking"]=TSMaster.animDB.animSetCollection[animSetID].animSet[1];
    12.  myOverrideController["_Attack"] = TSMaster.animDB.animSetCollection[animSetID].animSet[2];
    13.  anim.runtimeAnimatorController = myOverrideController;
    14.  
    15.  
    I use a GameObject to serve as my 'animation set database'. Loading the resources would be very time-consuming.

    Now each time I switch armor or weapons, I call LoadAnimationLayers(layerI'm Updating, animationSet) and it overrides the animations.

    Again, this may be harder than necessary, but I cannot find another solution.
     

    Attached Files:

  7. BotchedTaco

    BotchedTaco

    Joined:
    Jan 6, 2017
    Posts:
    3
    I know I am a bit late to here, but I just finished reading the book Procedural Content Generation for Unity Game Development. In chapter 6 it goes over generating modular weapons and adding scripted weapon animation.

    Essentially, they script the weapon animation, handling it outside of an animator. Couldn't you use the variables the animator uses to determine state to determine the animation for each of the layers you are wanting to create?

    It is a bit more work up front, but wrapping it in a coded state machine would prevent you from having to duplicate state machine logic for each layer you are working with.

    Code (CSharp):
    1. 1 void Update () {
    2. 2   if (inPlayerInventory) {
    3. 3     transform.position = player.transform.position;
    4. 4 if (weaponUsed == true) {
    5. 5 float degreeY = 0, degreeZ = -90f, degreeZMax = 275f;
    6. 6 Vector3 returnVecter = Vector3.zero;
    7. 7
    8. 8  transform.rotation = Quaternion.Slerp
    9.   (transform.rotation, Quaternion.Euler (0, degreeY,
    10.   degreeZ), Time.deltaTime * 20f);
    11. 9  if (transform.eulerAngles.z <= degreeZMax) {
    12. 10    transform.eulerAngles = returnVecter;
    13. 11    weaponUsed = false;
    14. 12    enableSpriteRender (false);
    15. 13      }
    16. 14    }
    17. 15  }
    18. 16 }