How can I make my "Squat" button register with just a press?

While testing out some of the things I’ve learnt so far in Unity, I’ve just encountered a problem I don’t understand. In the following script, I intend to make my 2D Player Character perform a squat animation once I press the “Space” key on my keyboard. He is expected to squat only when isSquatting is false and idle when the “Space” button is pressed and isSquatting is true. But this only happens very randomly while I press the key multiple times. I would be grateful if any knowledge to make my script better is shared.

using UnityEngine;
using System.Collections;
using UnityStandardAssets;

public class Player_Walk : MonoBehaviour {

// Variables used by the function "flipDirection"
private enum FaceDirection { FACINGLEFT = -1, FACINGRIGHT = 1};
FaceDirection fd = FaceDirection.FACINGRIGHT;
Vector3 localScale_temp = new Vector3();

// Variablies used by various functions
private Rigidbody2D thisRigidbody2D = null;
private Transform thisTransform = null;

// Variables used by the function "Walk"
string walk_axis = "Horizontal";
float walk_axis_val = 0f;
public float walk_speed = 500f;
Vector3 velocity_temp = new Vector3();
Animator walk_animator;

// Variables used by the function "Squat"
bool isSquatting = false;
string squat_button = "Jump";

void Awake () {
    thisRigidbody2D = GetComponent<Rigidbody2D>();
    thisTransform = GetComponent<Transform>();
    walk_animator = GetComponent<Animator>();
}

// Update is called once per frame
void Update () {
    Walk();
    Squat();
}

void Walk()
{
    if (isSquatting)
    {
        walk_animator.SetBool("startSquat", false);
    }
    walk_axis_val = UnityStandardAssets.CrossPlatformInput.CrossPlatformInputManager.GetAxis(walk_axis);
    thisRigidbody2D.AddForce(Vector2.right * walk_speed * walk_axis_val * Time.deltaTime);
    if (walk_axis_val != 0f)
    {
        walk_animator.SetBool("startWalk", true);
    }
    else{
        walk_animator.SetBool("startWalk", false);
    }
    Debug.Log("Velocity is " + thisRigidbody2D.velocity.ToString());

    velocity_temp = thisRigidbody2D.velocity; 
    velocity_temp.x  = Mathf.Clamp(velocity_temp.x, -10, 10);
    thisRigidbody2D.velocity = velocity_temp;

    if ((walk_axis_val < 0 && fd != FaceDirection.FACINGLEFT) || (walk_axis_val > 0 && fd != FaceDirection.FACINGRIGHT)){
        flipDirection();
        fd = (FaceDirection)((int)(fd) * -1);
    }
}

void flipDirection() {
    localScale_temp = thisTransform.localScale;
    localScale_temp.x *= -1;
    thisTransform.localScale = localScale_temp;
}

void Squat()
{
    if (UnityStandardAssets.CrossPlatformInput.CrossPlatformInputManager.GetButtonDown(squat_button) && !isSquatting)
    {
        walk_animator.SetBool("startSquat", true);
        isSquatting = true;
    }

    else if (UnityStandardAssets.CrossPlatformInput.CrossPlatformInputManager.GetButtonDown(squat_button) && isSquatting)
    {
        walk_animator.SetBool("startSquat", false);
        isSquatting = false;
    }
    
}

}

In your Squat() method you have a serious looping issue that keeps cancelling itself out. You’re trying to give too much direction. I’ll walk you through the corridors of your own code.

You only want this guy to squat when the button is pressed, right? So make that happen.

Your code as it is: When Squat() runs and you are holding down the space button at first, isSquatting is false and then it is set to true and you get what you want…squatting.

     if(UnityStandardAssets.CrossPlatformInput.CrossPlatformInputManager.GetButtonDown(squat_button) && !isSquatting)
     {
         walk_animator.SetBool("startSquat", true);
         isSquatting = true;
     }

But then Squat() runs around on the next Update() call, you are still holding the space key, and isSquatting is true… What do you think will occur? It skips past the first if statement because it no longer holds true and runs the “else if” piece.

 (UnityStandardAssets.CrossPlatformInput.CrossPlatformInputManager.GetButtonDown(squat_button) && isSquatting)
     {
         walk_animator.SetBool("startSquat", false);
         isSquatting = false;
     }

So, basically by doing things this way, you are making the character squat and not squat continuously. You are also doing this in your Walk() function, which I can imagine, between both of these loopings of on and off, looks very wonky, to say the least. This hurts your characters legs with all these muscle spasms. Let’s look at a different way. If we are holding in the button, we want to be squatting else, he’s not squatting.

void Update()
{
  if(Input.GetKey(KeyCode.Space))
  {
    Squat();
  }
  else
  {
     Walk();
  }
}

And your other code for your Walk() and Squat() functions get simplified too…

 void Walk()
 {
   walk_animator.SetBool("startSquat", false);
    isSquatting = false;

     walk_axis_val = UnityStandardAssets.CrossPlatformInput.CrossPlatformInputManager.GetAxis(walk_axis);
     thisRigidbody2D.AddForce(Vector2.right * walk_speed * walk_axis_val * Time.deltaTime);
     if (walk_axis_val != 0f)
     {
         walk_animator.SetBool("startWalk", true);
     }
     Debug.Log("Velocity is " + thisRigidbody2D.velocity.ToString());
     velocity_temp = thisRigidbody2D.velocity; 
     velocity_temp.x  = Mathf.Clamp(velocity_temp.x, -10, 10);
     thisRigidbody2D.velocity = velocity_temp;
     if ((walk_axis_val < 0 && fd != FaceDirection.FACINGLEFT) || (walk_axis_val > 0 && fd != FaceDirection.FACINGRIGHT)){
         flipDirection();
         fd = (FaceDirection)((int)(fd) * -1);
     }
 }

 void Squat()
 {
         walk_animator.SetBool("startWalk", false);
         walk_animator.SetBool("startSquat", true);
         isSquatting = true;
 }