Jumping randomly doesn't work

My problem is that when pressing the jump button, randomly the character won’t jump but it will play the jump animation.

I figure this is because I take in the input using Update() and then change a variable in another script using FixedUpdate(), but I could be wrong.

Input scirpt example:

void Update()
{
    motor.Jump = Input.GetButtonDown("Jump");
}

Motor script example:

void FixedUpdate()
   {
        if (canJump && jump && lastButtonDownTime < 0) 
		{
			lastButtonDownTime = Time.time;
		}

        if(isGrounded)
		{	
			if (!jump || !canJump) 
			{
				lastButtonDownTime = -100;
			}
			
			 //Jump only if the jump button was pressed down in the last 0.25 seconds.
	        if (canJump && jump && (Time.time - lastButtonDownTime < 0.25))
			{
				lastButtonDownTime = -100;
				rigidbody.AddForce(new Vector3(0, CalculateJumpVerticalSpeed(), 0), ForceMode.VelocityChange);
				isGrounded = false;
			}
		}
   }

Not sure why this is happening, any suggestions?

I had a similar problem once. Turned out it was in 3d modeling software.

I had to link the animated object to a dummy object which wasn’t moved.

As soon as your animation states the position in 3d modeling software, the character will be playing animation, but will get stuck in place. My problem was solved when I linked it to the stationary object and then exported it (with animation) to unity.

I found a solution.

The problem was that Update() and FixedUpdate() are not synchronized so occasionally the input script would set jump to true and then back to false between FixedUpdate() calls. So FixedUpdate() would only see jump == false and not perform a jump.

The solution was to only set jump to true in the input script and set it to false in the motor script. This way even if jump becomes true between FixedUpdate() calls it will still be true for the next call.

Input scirpt example:

void Update()
{
    if(Input.GetButtonDown("Jump"))
        motor.Jump = true;
}

Motor script example:

void FixedUpdate()
   {
       if (canJump && jump && lastButtonDownTime < 0) 
       {
         lastButtonDownTime = Time.time;
       }
 
        if(isGrounded)
       { 
         if (!jump || !canJump) 
         {
          lastButtonDownTime = -100;
         }
 
          //Jump only if the jump button was pressed down in the last 0.3 seconds.
          if (canJump && jump && (Time.time - lastButtonDownTime < 0.3))
         {
           lastButtonDownTime = -100;
           rigidbody.AddForce(new Vector3(0, CalculateJumpVerticalSpeed(), 0), ForceMode.VelocityChange);
           isGrounded = false;
           jump = false;
         }
       }
   }

void OnCollisionStay(Collision col)
{
  for(int i = 0; i < col.contacts.Length; i++)
  {
			//if contact has been made on the bottom of the character
			if(col.contacts*.point.y < (transform.position.y - topAndBottomOffset))*
  •  	{*
    
  •  		//on the ground*
    
  •  		isGrounded = true;*
    
  •  		jump = false;*
    
  •  	}*
    

}

}
This seems to be working perfectly now.