Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Animator Freezing on First Frame

Discussion in '2D' started by heytheremogwai, Sep 29, 2019.

  1. heytheremogwai

    heytheremogwai

    Joined:
    Mar 22, 2018
    Posts:
    36
    Hi,

    I'm working on a 2D, top-down RPG and I'm trying to use the animator to change animations based on movement... I can't figure out how to change the character to the "idle" animation when I release the movement keys...

    Code (CSharp):
    1. public class player_movement : MonoBehaviour
    2. {
    3.     public float default_speed = 1.0f;
    4.     public Animator anim;
    5.  
    6.     void Start(){
    7.         anim = GetComponent<Animator>();
    8.     }
    9.      
    10.     void Update () {
    11.         Vector2 pos = transform.position;
    12.  
    13.         if (Input.GetKey ("w")) {
    14.             anim.SetBool("walk_n", true);
    15.             pos.y += default_speed * Time.deltaTime;
    16.            if (Input.GetKeyUp("w"))
    17.             {
    18.                 anim.SetBool("walk_n", false);
    19.             }
    20.         }
    21.         if (Input.GetKey ("s")) {
    22.             anim.SetBool("walk_s", true);
    23.             pos.y -= default_speed * Time.deltaTime;
    24.          }
    25.  
    26.         if (Input.GetKey ("d")) {
    27.             anim.SetBool("walk_e", true);
    28.             pos.x += default_speed * Time.deltaTime;
    29.         }
    30.         if (Input.GetKey ("a")) {
    31.             anim.SetBool("walk_w", true);
    32.             pos.x -= default_speed * Time.deltaTime;
    33.         }
    34.          
    35.         transform.position = pos;
    36.     }
    37. }
    38.  
    I've tried to solve this (GetKeyUp?). When the bool is set to false, it should transition to the "idle_north" animation... What would be a way to accomplish this properly? Thank you.
     
  2. ZliVuk

    ZliVuk

    Joined:
    Mar 24, 2018
    Posts:
    61
    Try using Trigger instead of Bool for transitions.
     
  3. heytheremogwai

    heytheremogwai

    Joined:
    Mar 22, 2018
    Posts:
    36
    Hmm... I switched them all, and made all the correct connections with the animator... Still can't get the idle animations to trigger...
    Code (CSharp):
    1.     void Update () {
    2.         Vector2 pos = transform.position;
    3.  
    4.         if (Input.GetKeyUp("w"))
    5.         {
    6.             anim.SetTrigger("trig_idle_n");
    7.         }
    8.  
    9.         if (Input.GetKeyUp("a"))
    10.         {
    11.             anim.SetTrigger("trig_idle_w");
    12.         }
    13.  
    14.         if (Input.GetKeyUp("s"))
    15.         {
    16.             anim.SetTrigger("trig_idle_s");
    17.         }
    18.  
    19.         if (Input.GetKeyUp("d"))
    20.         {
    21.             anim.SetTrigger("trig_idle_e");
    22.         }
    23.  
    24.         if (Input.GetKey ("w")) {
    25.             anim.SetTrigger("trig_walk_n");
    26.             pos.y += default_speed * Time.deltaTime;
    27.         }
    28.  
    29.         if (Input.GetKey ("s")) {
    30.             anim.SetTrigger("trig_walk_s");
    31.             pos.y -= default_speed * Time.deltaTime;
    32.          }
    33.  
    34.         if (Input.GetKey ("d")) {
    35.             anim.SetTrigger("trig_walk_e");
    36.             pos.x += default_speed * Time.deltaTime;
    37.         }
    38.         if (Input.GetKey ("a")) {
    39.             anim.SetTrigger("trig_walk_w");
    40.             pos.x -= default_speed * Time.deltaTime;
    41.         }
    42.            
    43.         transform.position = pos;
    44.     }
     
  4. ZliVuk

    ZliVuk

    Joined:
    Mar 24, 2018
    Posts:
    61
    Do you have return transitions to Idle? All 4 (a,s,d,w) should have transition to them from idle on trigger, and back to idle without conditions?
     
  5. ZliVuk

    ZliVuk

    Joined:
    Mar 24, 2018
    Posts:
    61
    Oh, just noticed that you have separate Idle for each direction.
    But as you set that in code if animator is good it should work. Post screenshot of animator?
     
  6. ZliVuk

    ZliVuk

    Joined:
    Mar 24, 2018
    Posts:
    61
    You should use Any State as root for that animator. From Any State you have transition to w walk (for example) with anim.SetTrigger("trig_walk_n") and from that to w idle with condition anim.SetTrigger("trig_idle_w");
    No back transitions. Idle animations are loop and so are walk. That way player stays in idle, displays walk on keypress.
    I guess that you want player character to stay in idle that corespondents to last walk direction?
     
    heytheremogwai likes this.
  7. heytheremogwai

    heytheremogwai

    Joined:
    Mar 22, 2018
    Posts:
    36
    here is the animator...
     

    Attached Files:

  8. heytheremogwai

    heytheremogwai

    Joined:
    Mar 22, 2018
    Posts:
    36
    yes exactly... hmm
     
  9. ZliVuk

    ZliVuk

    Joined:
    Mar 24, 2018
    Posts:
    61
    So, Any State is the key difference. Please create new Animator don't destroy that one since it is rather intricate.
     
  10. ZliVuk

    ZliVuk

    Joined:
    Mar 24, 2018
    Posts:
    61
    Entry should go to some default Idle animation (with no conditions).
    Then from Any State create what I described before.
     
    heytheremogwai likes this.
  11. heytheremogwai

    heytheremogwai

    Joined:
    Mar 22, 2018
    Posts:
    36
    so I used all the proper triggers here, using the same code. still not working...hmm.. is this what you meant?
     

    Attached Files:

  12. ZliVuk

    ZliVuk

    Joined:
    Mar 24, 2018
    Posts:
    61
    Close but need more work.
    1) delete transition from idle_s to AnyState.
    2) for every walk_w add transition to idle_w with trigger "trig_idle_w"
    Any State transitions only to walk animations.
    Walk animations only transition to corespondent idle animations.
     
    mihalvysta and heytheremogwai like this.
  13. ZliVuk

    ZliVuk

    Joined:
    Mar 24, 2018
    Posts:
    61
    You will need Any State to some death animation for instance.
     
  14. ZliVuk

    ZliVuk

    Joined:
    Mar 24, 2018
    Posts:
    61
    Something like this.
     

    Attached Files:

    heytheremogwai likes this.
  15. ZliVuk

    ZliVuk

    Joined:
    Mar 24, 2018
    Posts:
    61
    That way character enters idle on start of scene. From that animation with code you provided should go to walk depending on button pressed, and from that to its idle. From that one goes to next walk depending on next button press.
     
  16. ZliVuk

    ZliVuk

    Joined:
    Mar 24, 2018
    Posts:
    61
  17. heytheremogwai

    heytheremogwai

    Joined:
    Mar 22, 2018
    Posts:
    36
    awesome, thank you so much for the help. it is almost there. it is moving in each direction, and it is reaching the idle states properly...however, when it does the "walk" direction, it seems to get stuck on the first frame, and it doesn't play it out....any idea why?
     
  18. heytheremogwai

    heytheremogwai

    Joined:
    Mar 22, 2018
    Posts:
    36
    I changed the code to be
    Code (CSharp):
    1.  if (Input.GetKeyDown ("s")) {
    2.             anim.SetTrigger("trig_walk_s");
    3.             pos.y -= default_speed * Time.deltaTime;
    4.          }
    GetKeyDown seems to play the animation out, but stops the actual movement??

    apparently there was something called "can transition to self" that you could check/uncheck in older versions of unity? would this fix it?
     
    Last edited: Sep 29, 2019
  19. ZliVuk

    ZliVuk

    Joined:
    Mar 24, 2018
    Posts:
    61
    It does that because Update checks every frame what is, in this case, pressed and on every frame that the button is pressed there is trigger and plays animation according to AnyState transition. Now, this can be solved in more than one way. For instance use, yeah I know, Bool on transition to walk:
    Code (CSharp):
    1.  
    2. if (Input.GetKeyDown ("s")&anim.GetBool("walk_s", false))
    3. {
    4.     anim.SetBool("walk_s", true)
    5.     pos.y -= default_speed * Time.deltaTime;
    6. }
    7. if (Input.GetKeyUp("s"))
    8. {
    9.     anim.SetBool("walk_s", false)
    10.     anim.SetTrigger("idle_s");
    11. }
    12.  
    Now, from AnyState transition to walk with Bool walk_s as true. From walk to idle on trigger idle_s.

    Maybe, for idle to work you will have to transition to idle from AnyState directly with trigger "idle_s" in this example.
    Then, maybe, you need to use Bool for idle also like this:
    Code (CSharp):
    1.  
    2. if (Input.GetKeyDown ("s")&anim.GetBool("walk_s", false))
    3. {
    4.     anim.SetBool("walk_s", true)
    5.     anim.SetBool("idle_s", false);  
    6.     pos.y -= default_speed * Time.deltaTime;
    7. }
    8. if (Input.GetKeyUp("s")&anim.GetBool("idle_s", false))
    9. {
    10.     anim.SetBool("idle_s", true);
    11.     anim.SetBool("walk_s", false)
    12. }
    13.  
     
    Last edited: Sep 30, 2019
  20. heytheremogwai

    heytheremogwai

    Joined:
    Mar 22, 2018
    Posts:
    36
    I'm sorry for bringing this back up, but I've been trying and trying different things, but this is about as close as I can get. How can I program this without the Update method resetting the animation to the first frame, making it look like it's frozen when I hold the key down? I tried setting a private bool, etc. I've done a lot of research, and apparently there was something called "can transition to self" that seems like it may resolve this issue, but it doesn't seem to be in newer versions of Unity..... Any thoughts here?

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5.  
    6.  
    7. public class player_movement : MonoBehaviour
    8. {
    9.     public float default_speed = 2.0f;
    10.     public Animator anim;
    11.  
    12.     void Start(){
    13.         anim = GetComponent<Animator>();
    14.     }
    15.        
    16.     void Update () {
    17.         Vector2 pos = transform.position;
    18.         if (Input.GetKeyUp("w"))
    19.         {
    20.             anim.SetBool("walk_n", false);
    21.         }
    22.      
    23.         if (Input.GetKeyUp("a"))
    24.         {
    25.             anim.SetBool("walk_w", false);
    26.         }
    27.  
    28.         if (Input.GetKeyUp("s"))
    29.         {
    30.             anim.SetBool("walk_s", false);
    31.         }
    32.  
    33.         if (Input.GetKeyUp("d"))
    34.         {
    35.             anim.SetBool("walk_e", false);
    36.         }
    37.  
    38.         if (Input.GetKey("w")){
    39.             anim.SetBool("walk_n", true);
    40.             pos.y += default_speed * Time.deltaTime;
    41.         }
    42.         if (Input.GetKey("s")){
    43.             anim.SetBool("walk_s", true);
    44.             pos.y -= default_speed * Time.deltaTime;
    45.         }
    46.  
    47.         if (Input.GetKey("d")) {
    48.             anim.SetBool("walk_e", true);
    49.             pos.x += default_speed * Time.deltaTime;
    50.         }
    51.         if (Input.GetKey("a")) {
    52.             anim.SetBool("walk_w", true);
    53.             pos.x -= default_speed * Time.deltaTime;
    54.         }
    55.            
    56.         transform.position = pos;
    57.     }
    58. }
    59.  
     
  21. ZliVuk

    ZliVuk

    Joined:
    Mar 24, 2018
    Posts:
    61
    I recreated similar project and found the solution. It is weird. Solution is for w or moving up.
    1) Animator: "Entry" transitions to some "default_idle" animation.
    "Any State" transitions to "walk_w" and "idle_w" animations with bool "walk_w"=true for "walk_w" and bool "idle_w"=true for "idle_w" animation. Each transition has enabled option in "Settings" for transition "Can transition to self". Animator in my case should have option "Apply root motion" enabled since one animation is moving gameobject and other rotating it.
    2) Script is:
    Code (CSharp):
    1. using UnityEngine;
    2.  
    3. public class script : MonoBehaviour
    4. {
    5.     public float default_speed = 10.0f; // Set speed from editor if needed
    6.     private Animator anim;
    7.     private Vector3 pos;
    8.  
    9.     // Start is called before the first frame update
    10.     void Start()
    11.     {
    12.         anim = GetComponent<Animator>();
    13.     }
    14.  
    15.     // Update is called once per frame
    16.     void Update()
    17.     {
    18.         pos = gameObject.transform.position;
    19.  
    20.         if (Input.GetKey ("w"))
    21.         {
    22.             anim.SetBool("walk_w", true);
    23.             anim.SetBool("idle_w", false);
    24.             pos.y += default_speed * Time.deltaTime;
    25.         }
    26.      
    27.         if (Input.GetKeyUp("w"))
    28.         {
    29.             anim.SetBool("walk_w", false);
    30.             anim.SetBool("idle_w", true);
    31.         }
    32.      
    33.         pos.z = 0; // One animation has rotation so this fixes that
    34.      
    35.         gameObject.transform.position = pos;
    36.     }
    37. }
     
  22. heytheremogwai

    heytheremogwai

    Joined:
    Mar 22, 2018
    Posts:
    36
    Can I ask what version of Unity you're running?
     
  23. ZliVuk

    ZliVuk

    Joined:
    Mar 24, 2018
    Posts:
    61
    Sure, 2019.2.6f1
     
  24. heytheremogwai

    heytheremogwai

    Joined:
    Mar 22, 2018
    Posts:
    36
    ahhh so that was it the whole time!!! i couldn't find "Can transition to self"~!!!! thanks so much all the help.
     
    ZliVuk likes this.
  25. ZliVuk

    ZliVuk

    Joined:
    Mar 24, 2018
    Posts:
    61
    Please rename topic name to something that can better describe problem so someone can find this and not spend days searching for solution :)