Input.GetButtonDown works half the time

void Update()
{
//look direction
lookRay = Camera.main.ScreenPointToRay(Input.mousePosition);
if (groundPlane.Raycast(lookRay, out distance))
{
ControlRotation();
target = lookRay.GetPoint(distance);
if (!Input.GetMouseButton(1))
transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(new Vector3(target.x, transform.position.y, target.z) - transform.position), Time.deltaTime*4);
}

        //movement
        if (controller.isGrounded)
        {
            float MovementSpeed = Speed;
            if (Input.GetButton("Sprint") && Stealth!=true)
            {
                MovementSpeed *= 2f;
            }
            //THIS THINGY DOESN'T WORK PROPERLY
            else if (Input.GetButtonDown("Crouch"))
            {
                if (Stealth==false)
                {
                    Stealth = true;
                    Debug.Log("Stealth on");
                }
                else if (Stealth==true)
                {
                    Stealth = false;
                    Debug.Log("Stealth off");
                }
                
            }
            else if (Stealth==true)
            {
                MovementSpeed *= 0.5f;
            }
            rightMovement = right * MovementSpeed * Time.deltaTime * Input.GetAxis("Horizontal");
            forwardMovement = forward * MovementSpeed * Time.deltaTime * Input.GetAxis("Vertical");
            Movement = rightMovement + forwardMovement;
            down = Vector3.zero;
        }
        else
        {
            down.y = down.y - (Gravity * Time.deltaTime);        
        }
        controller.Move(Movement + down);
    }

As you can see i’m calling it from an Update function, but it still doesn’t work and i just can’t understand why. I tried messing with if conditions in the movement segment but nothing changed.

Try moving everything that is essential to movement to fixedupdate, it may just be that every time you click the button the computer has to go through all that code before it can be done.

You need to call this function from the Update function, since the state gets reset each frame. *It will not return true until the user has released the key and pressed it again.

Had similar problems in a past project, alter the logic to use Input.GetButton worked for me.