Search Unity

Why won't my animations change?

Discussion in 'Getting Started' started by smatpat, Aug 2, 2020.

  1. smatpat

    smatpat

    Joined:
    Jul 27, 2020
    Posts:
    13
    Hi,

    I'm coding movement for a sprite, which the player can control with arrow keys. I've got the movement working, but I want the sprite animation to change from idle to running when an arrow key is held.

    I instinctively went to make an if-else sequence, but it won't work.

    Under the MonoBehaviour class, I wrote:
    Code (CSharp):
    1. private Animator anim;
    Under void Start, I wrote:
    Code (CSharp):
    1. anim = GetComponent<Animator>();
    I saw this in a tutorial and I'm not sure why it was necessary - please tell me if I should just get rid of it.

    Anyway, then I wrote my if-else sequence under void Update:
    Code (CSharp):
    1. if (Input.GetKeyDown(KeyCode.LeftArrow))
    2.                 anim.SetBool("isRunning", true);
    3.  
    4. else
    5.                 anim.SetBool("isRunning", false);
    In my animator, the sprite is set to change animations when 'isRunning' is true, and then change back when it's false.

    Where am I going wrong here?

    EDIT: I did a check with Debug.log so I can confirm that it's recognising the fact the left arrow key is pressed down. It must be a problem with my actual animation code?

    Thank you! :)
     
  2. Vryken

    Vryken

    Joined:
    Jan 23, 2018
    Posts:
    2,106
    It is always ideal to cache references to components like this because it's faster to use the cached reference than to call
    GetComponent
    every time, especially during Update/FixedUpdate/LateUpdate/etc.

    GetKeyDown is only true for the first frame that the input was detected. If you want to detect the input being held-down across multiple frames, use GetKey instead.

    Since all of the various
    GetKey...
    methods return a
    bool
    value, you can simplify your code by doing this:
    Code (CSharp):
    1. anim.SetBool("isRunning", Input.GetKey(KeyCode.LeftArrow));
     
    smatpat likes this.
  3. smatpat

    smatpat

    Joined:
    Jul 27, 2020
    Posts:
    13
    Thank you! That's a super helpful response.

    I implemented what you said and it works! Sort of.

    I used the code you suggested, then copied and pasted it for the right arrow key too. Like this:

    Code (CSharp):
    1. anim.SetBool("isRunning", Input.GetKey(KeyCode.LeftArrow));
    2. anim.SetBool("isRunning", Input.GetKey(KeyCode.RightArrow));
    Now, when I press the right arrow key, the animation changes as it's supposed to - but not when I press the left arrow key?
     
  4. Vryken

    Vryken

    Joined:
    Jan 23, 2018
    Posts:
    2,106
    Because you're doing two separate checks on the same frame, and since the right-key is checked after the left-key, that's the last condition that is setting the value of the animation. The value of the previous condition is overridden by this one.

    What you want is to use an or condition, to check if the left-key or the right-key is held down and apply the value to the animation once, like so:
    Code (CSharp):
    1. //Check if the left arrow OR the right arrow is held
    2. bool isRunning = Input.GetKey(KeyCode.LeftArrow) || Input.GetKey(KeyCode.RightArrow);
    3.  
    4. //Apply the result of the check to the animation.
    5. anim.SetBool("isRunning", isRunning);
     
    smatpat likes this.
  5. smatpat

    smatpat

    Joined:
    Jul 27, 2020
    Posts:
    13
    Thank you! I ended up scripting an if-else sequence that worked for me, but I've changed it to what you've written there because yours is far more streamlined - and makes more sense!

    That's really helpful - thank you :)
     
    Vryken likes this.