Search Unity

2D character control when using joint (bone) animations on complex characters

Discussion in '2D' started by grippie, Mar 16, 2018.

  1. grippie

    grippie

    Joined:
    Mar 16, 2018
    Posts:
    10
    I'm using some assets that I purchased from the asset store to do a top down Zelda A link to the past type of game. The characters that were in the set are amazing, but with the detail comes some complications for me.

    I'm new to unity, but not game development. I've worked on 2d simple animated sprite games, however the setup of these characters is confusing me. I'm not sure how to make them controlled by a script, or access the various animation states. All the tutorials I've seen only deal with simple 3 state sprite animation with one controller to access the states. i.e facing up, down, side, side flipped

    The character is divided into many, many sprites and there is a script for changing armor and all kinds of stuff to easily make a bunch of different types of characters. The problem I'm having is that these are made up of prefabs where the animators are connected to these sub states and not the main character node. Each direction has a set of very deep folders and the main directions of down, up, side each have a hierarchy. The animators are connected to each of those nodes and there is only one visible node at a time. i.e. in the image below up, left and right are not visible in the scene as they are unchecked.

    character heirarchy.PNG

    Each controller has it's own set of states. I'm not sure how to access all of these different states, or if I'm supposed to create a new all encompassing controller that attaches to the top node.

    animation controller down -> down idle, down walk, down attack etc
    animation controller side-> side idle, side walk, side attack etc
    animation controller up-> up idle, up walk, up attack etc

    Essentially I'm looking for some guidance on how to get my character moving around and switching over to the various directions and animations as my scripts can't seem to access the transform to make the character move in all directions.
     
  2. mrCharli3

    mrCharli3

    Joined:
    Mar 22, 2017
    Posts:
    976
    Hey,

    I'm using the same asset :) It's quite neat. I have a CharacterManager attached to the Parent with references to all the directions and animation controllers. And depending on the direction the character moves I set the corresponding animation :)

    Hope that helps!
     
  3. grippie

    grippie

    Joined:
    Mar 16, 2018
    Posts:
    10
    Thanks, I appreciate the reply. I played around for a few hours and was able to get the character to move and stab/bow/thrust and all of that. However, I can only do it in one direction, and my animation controller is messy. The character moves in all directions but won't switch animations.

    If I create the CharacterManager on the parent, I feel like I'm still missing a basic piece of how this all connect together.

    Are you using something like Animator[] anim = GetComponentsInChildren<Animator>(); to get the list of animators in the child objects? That returns the objects, but I'm not sure how to control the visibility of each direction. Basically I'm not sure how to hide down, left and right, when I only want the guy moving upwards. or in other words, only show the right animation when the character switches directions. Do you anim[0].Play("Male Character Side", 0); to connect to the right controller per each direction?

    Feels like I'm so close to understanding this so that I can get into the stuff that I'm actually good at like game design and level creation haha.
     
  4. mrCharli3

    mrCharli3

    Joined:
    Mar 22, 2017
    Posts:
    976
    Hmm, I don't have it in front of me but I do something like this in the CharacterManager (pseudoCode):


    Code (CSharp):
    1. GameObject downDir, upDir, leftDir, rightDir; //All directions
    2.  
    3. currentDir = downDir;
    4.  
    5. if(moving left)
    6. currentDir.SetActive(false);
    7. currentDir = leftDir;
    8. currentDir.SetActive(true);
    9. currentDir.GetComponent<Animator>().StartAnim();
     
  5. grippie

    grippie

    Joined:
    Mar 16, 2018
    Posts:
    10
    Nice! Thank you. I'm mostly there now. I have the character moving in all directions, and switching images (SetActive was the key) I just have to figure out some things with the play() function if that's what you were referring to by StartAnim();

    I have something like this, but have struggled trying to explicitly call the animation states so I get this weird moonwalking thing where the character doesn't transition to the walk animation until I let off of the direction key.

    keydown (upArrow) -->Idle animation sliding --> keyup --> 1 walk animation

    Code (CSharp):
    1. if (moving up)
    2.          moveDirection.y = 1;
    3.          currentDir.SetActive(false);
    4.          currentDir = upDir;
    5.          currentDir.SetActive(true);
    6.          currentDir.GetComponent<Animator>().Play(0);
    7.  
     
  6. mrCharli3

    mrCharli3

    Joined:
    Mar 22, 2017
    Posts:
    976
    This probably has something do do with how you transition between animations in your animator. For me I use a bool "moving" that is set to true when my char is moving, and if true then the character walks.
     
  7. grippie

    grippie

    Joined:
    Mar 16, 2018
    Posts:
    10
    Wanted to loop back and say thanks, and also throw out my code for any future use. Not optimized just yet so I know that it's not best practice, I'm just trying to get stuff working!

    I'm also looking to have the character move 8-way's but with only 4 animation directions. example if the char is moving right and up or down is pressed, the character should still face right but slide up or down. need to detect previousDir and somehow hold the right animation directions. tbd.

    Code (CSharp):
    1.    void Start()
    2.     {
    3. // since my character can be any direction depending on the way he enters a scene, I made this find the direction that they are facing first
    4.         if (currentDir == null)
    5.         {
    6.             if (downDir.activeSelf)
    7.                 currentDir = downDir;
    8.             else if (upDir.activeSelf)
    9.                 currentDir = upDir;
    10.             else if(rightDir.activeSelf)
    11.                 currentDir = rightDir;
    12.             else if(leftDir.activeSelf)
    13.                 currentDir = leftDir;
    14.         }
    15.  
    16. void FixedUpdate()
    17.     {
    18.         Vector2 moveDirection = Vector2.zero;
    19.         horizontal = Input.GetAxisRaw("Horizontal");
    20.         vertical = Input.GetAxisRaw("Vertical");
    21.         isWalking = false;
    22.         moveDirection.x = horizontal;
    23.         moveDirection.y = vertical;
    24.         if (Mathf.Abs(horizontal) > 0 || Mathf.Abs(vertical) > 0)
    25.             isWalking = true;
    26.         else
    27.             isWalking = false;
    28.  
    29. // animations didn't start again if the character faced the same direction and went back to idle. maybe not perfect, so I only do this if the character direction changes, or if he is idle.
    30. if (horizontal < 0)
    31.         {
    32.            // if character is not facing the same direction, or character is idle, then reset the active direction as current
    33.             if (!currentDir.Equals(leftDir) || currentDir.GetComponent<Animator>().GetBool("Idle"))
    34.             {
    35.                 currentDir.SetActive(false);
    36.                 currentDir = leftDir;
    37.                 currentDir.SetActive(true);
    38.                 currentDir.GetComponent<Animator>().Play(0);
    39.                 currentDir.GetComponent<Animator>().SetBool("Idle", false);
    40.             }
    41. other directions etc.
    42.  
    43. // detect for idle state, or move character
    44.         if (!isWalking)
    45.         {
    46.             currentDir.GetComponent<Animator>().SetBool("Idle", true);
    47.         }
    48.         else
    49.         {
    50.             transform.Translate(moveDirection * speed * Time.deltaTime);
    51.         }
    52.  
    53. }
    54.  
     
  8. mrCharli3

    mrCharli3

    Joined:
    Mar 22, 2017
    Posts:
    976
    nice gz. What I do is I just use the key most recently pressed for controlling anim direction