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

Basic question, toggle boolean on end animation

Discussion in 'Animation' started by Reloque, Aug 29, 2016.

  1. Reloque

    Reloque

    Joined:
    Apr 28, 2015
    Posts:
    207
    I am building a platform style 2d game. Mostly to learn about unity.

    I've got a player character, he can move, jump and swing his weapon. Now, I want a player character to stop moving once he swings his weapon. I've done this by toggling a boolean;

    private bool swinging

    As long as this is false, the character can move, once he starts swinging his weapon, the boolean is toggled and he stops moving. However, once the swinging animation is done, I have no way of toggling the bool, there is no way to inform my controller that the animation is over, the swing is complete. Not that I can find that is, I am probably missing something. Anyone have a suggestion?
     
  2. pixpusher2

    pixpusher2

    Joined:
    Oct 30, 2013
    Posts:
    121
  3. Mecanim-Dev

    Mecanim-Dev

    Joined:
    Nov 26, 2012
    Posts:
    1,675
  4. Reloque

    Reloque

    Joined:
    Apr 28, 2015
    Posts:
    207
    Okay, I am trying the state machine behaviour, but how do I get a reference to the Player gameobject?
     
  5. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,294
    OnStateEnter/Exit sends the animator in as a component, you can GetComponent<Player> on that.

    Note that there's a hidden issue here: OnStateEnter and Exit doesn't work like you'd think they should. So if you transition from state A to state B, there's no guarantee that A.OnStateExit fires before B.OnStateEnter. In fact, they'll usually come in the opposite order, unless transition time is 0

    It won't be a problem if you're only setting this bool in one state, but if you're setting the same bool in two different states and transition between them. Say you add a PowerAttack state, and add the same stateMachineBehaviour script to that state. If you transition from Attack to PowerAttack, PowerAttack.OnStateEnter will set swing to true in it's enter, and then Attack will set it false in it's OnStateExit, leaving you able to move during the PowerAttack state.
     
  6. Mecanim-Dev

    Mecanim-Dev

    Joined:
    Nov 26, 2012
    Posts:
    1,675
    @Baste Interesting, I wasn't aware of this issue. A few week ago i did write a thread about Statemachine behaviour review where I asked feedback from user about what they think is broken and need to be fixed but nobody answered.

    Taking note.
     
  7. Mecanim-Dev

    Mecanim-Dev

    Joined:
    Nov 26, 2012
    Posts:
    1,675
    @Baste ah i missed readed you, yeah this is expected if you have a transition time > 0.

    But still if you have any comment about SMB i would like to heard them, but let not hijack this thread.
     
  8. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,294
    Link? Didn't spot that. I've got... a lot of feedback. I think I've expressed some of it before.

    EDIT: Forget it, realized I could just check your thread history :p
     
  9. Reloque

    Reloque

    Joined:
    Apr 28, 2015
    Posts:
    207
    It works, thanks.
     
  10. NoneyaBiznazz

    NoneyaBiznazz

    Joined:
    Jul 23, 2017
    Posts:
    2
    Just for anyone else searching to solve this problem, I managed it by making an animation clip that changes a bool in the player controller. It doesn't work directly because it reverts when the clip is done. BUT you can have a short method to watch that bool and change your movement bool when it changes.. and another bool and animation clip to change it back. SetMoveableFalse and SetMoveableTrue are temporarily changed by animation clips, which are added to Timelines.

    public bool Moveable = false;
    public bool SetMoveableTrue = false;
    public bool SetMoveableFalse = false;

    void Keychecks(){

    if(SetMoveableFalse) Moveable = false;
    if(SetMoveableTrue) Moveable = true;
    if(!Moveable) return;

    ...
    ...
    }
     
  11. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,553
    I also have a solution to this problem: since needing to do something when an animation finishes is extremely common, I built it in as one of the main features of Animancer (link in my signature). With it, your code might look like this:

    Code (CSharp):
    1. [SerializeField] private AnimancerComponent _Animancer;
    2. [SerializeField] private AnimationClip _Idle;
    3. [SerializeField] private AnimationClip _Attack;
    4.  
    5. private bool _CanMove;
    6.  
    7. public void Attack()
    8. {
    9.     _CanMove = false;
    10.  
    11.     var state = _Animancer.Play(_Attack);
    12.     state.OnEnd = () =>
    13.     {
    14.         _CanMove = true;
    15.         _Animancer.Play(_Idle);
    16.     };
    17. }
    I've found that this approach is much more reliable than others because the script clearly defines how the action works rather than telling it to play an animation and just hoping that the Animator Controller is set up for the animation to do something extra when it ends.