Search code examples
c#unity-game-engineanimator

How to refrain button input until after an animation has finished playing in unity 5?


I am new to Unity and a beginner programmer. I experimented with Unity's GUI (canvas, button, label, etc...).

For the button, I made a class ButtonClickScript, so that when i tapped on the button, the variable waterBucketAmnt would increase until it reached 3. I then decided to take my experiment a little farther, so I created a very simple animation of a guy dumping a bucket of water. I wanted to restrict the amount of times the guy could dump the water using the waterBucketAmnt.

I can tap the GUI button 3 times and everything works fine. int waterBucketAmnt = 3. I then start the game and press the configured "Fire3" action on the keyboard and it does exactly as expected. The problem is that I can tap the "Fire3" action consecutively in less than a second, therefore, waterBucketAmnt = 0 and the animation plays only once. How can I delay input until the animation is completed?

using UnityEngine;
using System.Collections;

public class waterBucketAction : MonoBehavior {

Animator waterAnim;
// a simple player controller using unity's RigidBody2D feature. I added PlayerControllerScript so that I could make sure the player had to remain on the ground in order to dump the bucket of water. checkGround is so that I could inherit the grounded gameObject I created. 

PlayerControllerScript checkGround;
public ButtonClickScript checkWaterAmnt;

void Start () {
    checkGround = FindObjectOfType <playerControllerScript> ();
    waterAnim = GetComponent<Animator> ();
}

void FixedUpdate() {
    waterAnim.SetBool ("isPlaying", false);

    if (checkWaterAmnt.waterBucketAmnt > 0 && !waterAnim.GetCurrentAnimatorStateInfo(0).IsName("waterBucketAnimation")) {

        if (checkGround.grounded == true && Input.GetButtonDown ("Fire3")) {
            waterAnim.SetBool("isPlaying", true);

            //I need to wait for the animation to complete or delay the input. I searched multiple places and the best answer I could find was Animation.IsAnimating, but that seems to be deprecated? The API says that Animator replaced Animation, but I couldn't find an equivalent method.
            if(waterAnim.GetCurrentAnimatorStateInfo(0).IsName("waterBucketAnimation"))
                checkWaterAmnt.waterBucketAmnt -=1;
        }
    }

Solution

  • I am guessing that you ButtonClickScript looks like this:

    public class ButtonClickScript : MonoBehavior, IPointerClickHandler
    {
        public int waterBucketAmnt;
    
        void OnPointerClick() 
        {
            if (waterBucketAmnt < 3)
                waterBucketAmnt++;
        }
    }
    

    So what you need to do to delay the input is change the Interactable state of the button after is clicked by adding this line:

    if (waterBucketAmnt < 3)
    {
        waterBucketAmnt++;
        this.GetComponent<Button>().Interactable = false;
        //If Interactable is not accessible from code you could also use
        //this.gameObject.SetActive(false);
    }
    

    Then in the waterBucketAction script, you need to change the Interactable state of the button back to true once the animation is finished:

    void FixedUpdate(}
    {  
        //The 0 is the Layer Index
        if (this.animator.GetCurrentAnimatorStateInfo(0).IsName("YourWaterAnimationName"))
            checkWaterAmnt.GetComponent<Button>().Interactable = true;
    }