Search Unity

Need help with RPG character animation

Discussion in '2D' started by TheWebExpert, Sep 3, 2021.

  1. TheWebExpert

    TheWebExpert

    Joined:
    Apr 14, 2015
    Posts:
    198
    I have a game I'm working on; it's currently a visual duplicate of "The Legend of Zelda: A Link to the Past." I'm using that as the framework to develop the game; if I can duplicate Link, I can re-tool it to MY game.

    I'm having difficulty with the animation controller. Link has eight states: WalkE, IdleE, WalkN, IdleN, etc. I tried triggers. I tried programming. I just can't get this to work.

    The default starting position is IdleE. If you press right, Link should do the animated WalkE, then revert to IdleE. If you press left, Link should do the animated WalkW, then revert to IdleW. However, the program is all over the place.

    I can send you the complete package. I really, REALLY need some help on this!
     
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,697
    Go back to any one of the hundreds of basic Mecanim tutorials. There's only a few key parts. You need to grasp this stuff if you want to have even the slightest hopes of duplicating something as massively animated as a LoZ game. If someone else does it for you then they might as well do the entire game.
     
  3. Unrighteouss

    Unrighteouss

    Joined:
    Apr 24, 2018
    Posts:
    599
    Hey,

    So the question was already answered and Kurt-Dekker is likely way more experienced than myself and is correct, but I spent a few minutes typing up an answer already, so I'll post it anyway haha.

    Something that worked for me when dealing with a similar setup was using multiple animation controllers (one for each cardinal direction). In your case, you would create 4 identical animator controllers, each with a different pair of idle/walk animations setup the same way. Then in code, you would simply use
    Animator.runtimeAnimatorController
    to swap between them.

    Just to be clear, this is a method that I personally discovered and find easy to understand/manage, and I'm positive that accomplishing this functionality in a single Animator Controller is more than possible, and likely better. This method also only works if you don't use transitions, as you can't transition between animator controllers as far as I know.

    Here is an example of how it's setup:
    Code (CSharp):
    1.     // Order of controllers is: North / West / South / East --- WASD Keys
    2.     [SerializeField] AnimatorController[] controllers;
    3.    
    4.     Animator anim;
    5.  
    6.     void Start()
    7.     {
    8.         anim = GetComponent<Animator>();
    9.     }
    10.  
    11.     void Update()
    12.     {
    13.         if (Input.GetKey(KeyCode.W))
    14.         {
    15.             anim.runtimeAnimatorController = controllers[0];
    16.         }
    17.  
    18.         else if (Input.GetKey(KeyCode.A))
    19.         {
    20.             anim.runtimeAnimatorController = controllers[1];
    21.         }
    22.  
    23.         else if (Input.GetKey(KeyCode.S))
    24.         {
    25.             anim.runtimeAnimatorController = controllers[2];
    26.         }
    27.  
    28.         else if (Input.GetKey(KeyCode.D))
    29.         {
    30.             anim.runtimeAnimatorController = controllers[3];
    31.         }
    32.     }
    You drag each of the animator controllers into an array and then switch between them depending on which direction the player is moving. This is just an example.

    If you'd like to try this method and are struggling with anything, feel free to ask questions.
     
  4. TheWebExpert

    TheWebExpert

    Joined:
    Apr 14, 2015
    Posts:
    198
    That actually worked great! Now I'm wondering if it's possible to change what I have - which is Input.GetKeyDown - to accept held keys.
     
  5. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,697
    You want
    Input.GetKey()
     
  6. TheWebExpert

    TheWebExpert

    Joined:
    Apr 14, 2015
    Posts:
    198
    Yes, I did that. However, on the "down" key, he zooms ALL the way down, not simply one space at a time while the key is held.

    Code (CSharp):
    1.         if (Input.GetKey(KeyCode.DownArrow))
    2.           {
    3.             Anim.runtimeAnimatorController = Controllers[2];
    4.             if (Room[Game[CurrGame].X + 1, Game[CurrGame].Y] == "1")
    5.               {
    6.                 Anim.SetTrigger("South");
    7.                 Game[CurrGame].X += 1;
    8.                 Link.transform.localPosition = new Vector3(CurrX, Mathf.Lerp(CurrY - 64, CurrY,  .25F), 1);
    9.                 CurrY -= 64;
    10.                 Anim.SetTrigger("IdleS");
    11.               }
    12.             else
    13.               {
    14.                 Anim.SetTrigger("IdleS");
    15.               }
    16.             North = false;
    17.             East = false;
    18.             South = true;
    19.             West = false;
    20.           }
    21.  
    The code worked fine for GetKeyDown - moving one space at a time. But I want move once space at a time WHILE holding down the key - in other words, as long as I'm holding DOWN, keep moving one space down - at a time, not the whole range of down movement at once. I'm sure it's a simple fix.
     
  7. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,697
    Steps to success:

    - keep track of whether you are moving between spaces or not (since you are using an Animator, I imagine that an appropriately-configured StateMachineBehavior could be useful here)

    - ONLY read Input.GetKey() to adjust to the next frame when you are NOT moving between spaces.
     
  8. TheWebExpert

    TheWebExpert

    Joined:
    Apr 14, 2015
    Posts:
    198
    So, maybe a bool MovingSouth = true if GetKey, and then false when the key is up?
     
  9. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,697
    No, you need to query when it is done moving through your animation, as I noted above.