Can't jump while crouched.

I’ve been modifying a FPS controller script to suit what I need for my project but for some reason I am unable to jump while crouched. I have been looking over the code and I seem to be missing something because I cannot identify where the problem is.

using UnityEngine;
using System.Collections;
 
[RequireComponent (typeof (CharacterController))]
public class FPSControls: MonoBehaviour {
 
public float crouchSpeed = 3.0f;
	
public float walkSpeed = 5.0f;
 
public float runSpeed = 11.0f;
 
// If true, diagonal speed (when strafing + moving forward or back) can't exceed normal move speed; otherwise it's about 1.4 times faster
public bool limitDiagonalSpeed = true;
 
public bool jumpBoost = false;
public float jumpSpeed = 8.0f;
public float gravity = 20.0f;
 
// Units that player can fall before a falling damage function is run. To disable, type "infinity" in the inspector
public float fallingDamageThreshold = 10.0f;
 
// If the player ends up on a slope which is at least the Slope Limit as set on the character controller, then he will slide down
public bool slideWhenOverSlopeLimit = false;
 
// If checked and the player is on an object tagged "Slide", he will slide down it regardless of the slope limit
public bool slideOnTaggedObjects = false;
 
public float slideSpeed = 12.0f;
 
// If checked, then the player can change direction while in the air
public bool airControl = false;
 
// Small amounts of this results in bumping when walking down slopes, but large amounts results in falling too fast
public float antiBumpFactor = .75f;
 
// Player must be grounded for at least this many physics frames before being able to jump again; set to 0 to allow bunny hopping
public int antiBunnyHopFactor = 1;
	
public int decelLimit = 50;
	
private int decelTimer = 0; 
private Vector3 moveDirection = Vector3.zero;
private bool grounded = false;
private CharacterController controller;
private Transform myTransform;
private float speed;
private RaycastHit hit;
private float fallStartLevel;
private bool falling;
private float slideLimit;
private float rayDistance;
private Vector3 contactPoint;
private bool playerControl = false;
private int jumpTimer;
private bool running = false;
private bool wasGrounded = true;
private float height;
 
void Start() {
	controller = GetComponent<CharacterController>();
	myTransform = transform;
	speed = 0;
	rayDistance = controller.height * .5f + controller.radius;
	slideLimit = controller.slopeLimit - .1f;
	jumpTimer = antiBunnyHopFactor;
	height = controller.height;
}
 
void FixedUpdate() {
	float inputX = Input.GetAxis("Horizontal");
	float inputY = Input.GetAxis("Vertical");
	// If both horizontal and vertical are used simultaneously, limit speed (if allowed), so the total doesn't exceed normal move speed
	float inputModifyFactor = (inputX != 0.0f && inputY != 0.0f && limitDiagonalSpeed)? .7071f : 1.0f;
	float h = height;
 
	if (grounded) {
		// If we were not grounded, we are now
		// Start the deceleration timer and decrease speed to walkSpeed if it is higher than walkSpeed.
		if(wasGrounded == false) {
			decelTimer++;
			if(decelTimer >= decelLimit) {
				wasGrounded = true;
				decelTimer = 0;
			}
		}
		bool sliding = false;
		// See if surface immediately below should be slid down. We use this normally rather than a ControllerColliderHit point,
		// because that interferes with step climbing amongst other annoyances
		if (Physics.Raycast(myTransform.position, -Vector3.up, out hit, rayDistance)) {
			if (Vector3.Angle(hit.normal, Vector3.up) > slideLimit)
				sliding = true;
		}
		// However, just raycasting straight down from the center can fail when on steep slopes
		// So if the above raycast didn't catch anything, raycast down from the stored ControllerColliderHit point instead
		else {
			Physics.Raycast(contactPoint + Vector3.up, -Vector3.up, out hit);
			if (Vector3.Angle(hit.normal, Vector3.up) > slideLimit)
				sliding = true;
		}
 
			// If we were falling, and we fell a vertical distance greater than the threshold, run a falling damage routine
		if (falling) {
			falling = false;
			if (myTransform.position.y < fallStartLevel - fallingDamageThreshold)
				FallingDamageAlert (fallStartLevel - myTransform.position.y);
		}
 
		// If running isn't on a toggle, then use the appropriate speed depending on whether the run button is down
		//if (!toggleRun)
		//speed = Input.GetButtonDown("Run")? runSpeed : walkSpeed;
		if (Input.GetButton("Run")) {
			speed = runSpeed;
			running = true;
		} else if(inputY == 0 && inputX == 0) {
			// Slow down gradually to walk speed.
			if(speed > 0) {
				speed -= speed/2.0f;		
			} else {
				speed = 0;
			}
			running = false;
		} else if(Input.GetButton("Crouch")) {
			if(speed > crouchSpeed) {
				speed -= 0.5f; // slow down when crouching
			} else {
				speed = crouchSpeed;		
			}
		} else {
			if(speed > walkSpeed) {
					speed -= 0.4f;
			} else {
				speed = walkSpeed;		
			}
		}
 
		// If sliding (and it's allowed), or if we're on an object tagged "Slide", get a vector pointing down the slope we're on
		if ( (sliding && slideWhenOverSlopeLimit) || (slideOnTaggedObjects && hit.collider.tag == "Slide") ) {
			Vector3 hitNormal = hit.normal;
			moveDirection = new Vector3(hitNormal.x, -hitNormal.y, hitNormal.z);
			Vector3.OrthoNormalize (ref hitNormal, ref moveDirection);
			moveDirection *= slideSpeed;
			playerControl = false;
		}
		// Otherwise recalculate moveDirection directly from axes, adding a bit of -y to avoid bumping down inclines
		else {
			if(inputY == 0 && speed != 0 && wasGrounded == false) {
				moveDirection = new Vector3(inputX * inputModifyFactor, -antiBumpFactor, Mathf.Abs(inputX) * inputModifyFactor * 0.5f);
				moveDirection = myTransform.TransformDirection(moveDirection) * speed;
				playerControl = true;		
			} else {
				moveDirection = new Vector3(inputX * inputModifyFactor, -antiBumpFactor, inputY * inputModifyFactor);
				moveDirection = myTransform.TransformDirection(moveDirection) * speed;
				playerControl = true;
			}
		}
		if(Input.GetButton("Crouch")) {
			h = 0.5f * height;
			if(speed > crouchSpeed) {
				speed -= 0.5f; // slow down when crouching
			}
		}
 
		// Jump! But only if the jump button has been released and player has been grounded for a given number of frames
		if (!Input.GetButtonDown("Jump")) {
			jumpTimer++;
		} else if (jumpTimer >= antiBunnyHopFactor) {
			if(speed < runSpeed && speed > walkSpeed) {
				jumpBoost = true;
			}
			moveDirection.y = jumpSpeed;
			jumpTimer = 0;
		}
			
	}
	else {
			// If we were grounded, we aren't now
		if(wasGrounded == true) {
			decelTimer = 0;
			wasGrounded = false;
		}
		// If we stepped over a cliff or something, set the height at which we started falling
		if (!falling) {
			falling = true;
			fallStartLevel = myTransform.position.y;
		}
 
		// If air control is allowed, check movement but don't touch the y component
		if (airControl && playerControl) {
			if(inputY != 0) {
				moveDirection.x = inputX * speed * inputModifyFactor * 0.5f;
				moveDirection.z = speed * inputModifyFactor;
				moveDirection = myTransform.TransformDirection(moveDirection);
			} else if(moveDirection.z == 0) {
				moveDirection.x = inputX * speed * inputModifyFactor * 0.5f;
				moveDirection.z = inputY * inputModifyFactor;
				moveDirection = myTransform.TransformDirection(moveDirection);	
			}
		}
		if(Input.GetButton("Crouch")) {
			h = 0.5f * height;
		}
	}
 
	//Debug.Log(speed);
	
	// Apply gravity
	moveDirection.y -= gravity * Time.deltaTime;
 
	// Move the controller, and set grounded true or false depending on whether we're standing on something
	grounded = (controller.Move(moveDirection * Time.deltaTime) & CollisionFlags.Below) != 0;
		
	if(jumpBoost) {
		speed += 0.4f;	
		jumpBoost = false;
	}
	
	// Adjust the speed of the player so they slide after hitting the ground
	if(grounded && !Input.GetButton("Run") && speed > walkSpeed) {
		speed -= 0.4f;
	}
	
	// Adjust the controller height for crouching
	float lastHeight = controller.height; // crouch/stand up smoothly
	controller.height = Mathf.Lerp(controller.height, h, 5*Time.deltaTime);
	myTransform.position = new Vector3(myTransform.position.x, 
									myTransform.position.y + (controller.height - lastHeight)/2, 
									myTransform.position.z); // fix vertical position
		
	Debug.Log (speed);
	
		
}
 
void Update () {
	// If the run button is set to toggle, then switch between walk/run speed. (We use Update for this...
	// FixedUpdate is a poor place to use GetButtonDown, since it doesn't necessarily run every frame and can miss the event)
	if (grounded && Input.GetButtonDown("Run")) {
		if(speed < runSpeed) {
			speed += 0.5f;
		}
	}
}
 
// Store point that we're in contact with for use in FixedUpdate if needed
void OnControllerColliderHit (ControllerColliderHit hit) {
	contactPoint = hit.point;
}
 
// If falling damage occured, this is the place to do something about it. You can make the player
// have hitpoints and remove some of them based on the distance fallen, add sound effects, etc.
void FallingDamageAlert (float fallDistance) {
	print ("Ouch! Fell " + fallDistance + " units!");
}
}

I’ve added the following lines to the script just before setting the grounded variable:

Debug.Log ("Are we crouching? " + Input.GetButton("Crouch") + "Are we grounded? " + grounded);
	Debug.Log ("Are we trying to jump? " + Input.GetButtonDown ("Jump"));

It doesn’t seem to be registering any Jump key presses but I’ve tested it with other keys and they are working fine. so I think it’s an issue just involving the space bar.

It would be helpful if you place some Debug.log throughout your code in order to determine which logic path your code is following during attempting to jump.

The most likely issue is that at line 211:
grounded = (controller.Move(moveDirection * Time.deltaTime) & CollisionFlags.Below) != 0;
If your crouching is affecting your player’s hit box in a way that it is not detecting collisions with the ground then you wont be able to jump.

I would suggest trying to use CharacterController’s existing isGrounded property:

Otherwise test and see what logic path is occurring and I’ll gladly try to help further.