Forum begins after the advertisement:
[Part 1] Jump continues to trigger in midair
Home › Forums › Video Game Tutorial Series › Creating a Metroidvania in Unity › [Part 1] Jump continues to trigger in midair
- This topic has 12 replies, 3 voices, and was last updated 57 minutes ago by
Ser Apustaja.
-
AuthorPosts
-
March 28, 2025 at 7:10 pm #17644::
@doctorfrostbloom asks:
So here’s a unique one I didn’t see an answer for. I completely wrote down all of the code perfectly, but the character can still jump again midair despite the code saying it shouldn’t. It’s the exact same code, this is what I wrote:
public bool Grounded() { if(Physics2D.Raycast(GroundCheck.position, Vector2.down, groundCheckY, whatIsGround) || Physics2D.Raycast(GroundCheck.position + new Vector3(groundCheckX, 0, 0), Vector2.down, groundCheckY, whatIsGround) || Physics2D.Raycast(GroundCheck.position + new Vector3(-groundCheckX, 0, 0), Vector2.down, groundCheckY, whatIsGround)) { return true; } else { return false; } } void Jump() { if(Input.GetButtonUp("Jump") && rb.velocity.y > 0) { rb.velocity = new Vector2(rb.velocity.x, 0); } if (Input.GetButtonDown("Jump") && Grounded()) { rb.velocity = new Vector3(rb.velocity.x, jumpForce); } }
If this is supposed to stop them from jumping again, why does it still do it? Did I do something wrong, or miss something? (GroundCheck is my own variable, works the same as GroundCheckPoint)
March 28, 2025 at 7:15 pm #17645::It looks like you’ve got a good start, but there might be a few things to check to ensure that your character can’t jump again midair. Here are some suggestions:
-
Check the GroundCheck Position: Ensure that the
GroundCheck
position is correctly set and actually positioned below the character. If it’s too high or not aligned properly, the raycasts may not detect the ground correctly. -
Raycast Distance: Make sure that the
groundCheckY
value is sufficient to reach the ground. If it’s too short, the raycasts may not hit the ground. -
Layer Mask: Check that the
whatIsGround
layer mask is correctly set up to include the layers of the ground objects. If it’s not set correctly, the raycasts will not register any ground objects. -
Jump Input Handling: You might want to modify your input handling slightly. Instead of checking
Input.GetButtonUp("Jump")
, consider removing that check altogether or adjusting it. This way, you ensure that the jump logic only runs when the jump button is pressed down and the character is grounded. -
Debugging: Add debug logs to check if the
Grounded()
method is returning the expected values. For example:public bool Grounded() { bool isGrounded = Physics2D.Raycast(GroundCheck.position, Vector2.down, groundCheckY, whatIsGround) || Physics2D.Raycast(GroundCheck.position + new Vector3(groundCheckX, 0, 0), Vector2.down, groundCheckY, whatIsGround) || Physics2D.Raycast(GroundCheck.position + new Vector3(-groundCheckX, 0, 0), Vector2.down, groundCheckY, whatIsGround); Debug.Log("Is Grounded: " + isGrounded); return isGrounded; }
-
Check for Other Scripts: Ensure that there aren’t any other scripts affecting the jump behavior or modifying the Rigidbody’s velocity unexpectedly.
-
Rigidbody Constraints: If the character can jump while in a state that it shouldn’t (like when falling), consider freezing the Y-axis velocity or adding a cooldown for jumping.
Here’s an updated version of your
Jump()
method with the suggested changes:void Jump() { if (Input.GetButtonDown("Jump") && Grounded()) { rb.velocity = new Vector2(rb.velocity.x, jumpForce); } }
Try these suggestions and see if they help resolve the issue!
March 28, 2025 at 7:18 pm #17646::You’ll need to check whether your
Grounded()
function is working correctly, because that is likely what’s causing the issue with the jump triggering multiple times.I would first point you to check your What Is Ground attribute — make sure it has the correct layers checked. Also, make sure your terrain sprites are all assigned to the correct layer.
If all these are assigned, and you still have your character jumping in midair, you can modify
Grounded()
to display the current grounded status (see below). This will give you an idea of when in the game your character is grounded and not, which may help us identify the cause.public bool Grounded() { if(Physics2D.Raycast(GroundCheck.position, Vector2.down, groundCheckY, whatIsGround) || Physics2D.Raycast(GroundCheck.position + new Vector3(groundCheckX, 0, 0), Vector2.down, groundCheckY, whatIsGround) || Physics2D.Raycast(GroundCheck.position + new Vector3(-groundCheckX, 0, 0), Vector2.down, groundCheckY, whatIsGround)) { print("Player is grounded"); return true; } else { print("Player is NOT grounded"); return false; } }
March 29, 2025 at 8:39 am #17649::Alright your change of the
(Input.GetButtonUp)
seemed to have done the trick. I modified it to simply the opposite of(Input.GetButtonDown)
, and that worked. The character can no longer jump midair indefinitely. However, the custom jump height now does not work, and only works when you press the button again during a jump, which is weird. As I said before, I followed everything in the tutorial, so this is a really weird bug I’m having for no reason. Is this a string that just needs to be completely rewritten or did I miss something somewhere? At least I don’t have to worry about it not jumping midair anymore, but now you can’t control the jump height.March 29, 2025 at 9:05 pm #17655::Does your jumping still work if you remove the
GetButtonUp()
part entirely?void Jump() {
if(Input.GetButtonUp("Jump") && rb.velocity.y > 0) { rb.velocity = new Vector2(rb.velocity.x, 0); }if (Input.GetButtonDown("Jump") && Grounded()) { rb.velocity = new Vector3(rb.velocity.x, jumpForce); } }March 30, 2025 at 3:55 am #17656::Huh, strangely enough I have encountered another bug when I tried removed the GetButtonUp() part. When I do, it takes away the ability to let go and cancel the jump, like how I thought, but now I realized that you actually can still jump again indefinitely after a second, around the time you usually land.
After putting the code back, I even realized this still happened with the cancel jump code. So either there is some error in the other code and not this that’s regarding the ground check (I have the layers set to ground and the check point at the bottom of the player) or some other factor.
Here’s some of the code for what could potentially be problems:
[Header("Ground Check Settings")] [SerializeField] private float jumpForce = 45f; [SerializeField] private Transform GroundCheck; [SerializeField] private float groundCheckY = 0.2f; [SerializeField] private float groundCheckX = 0.5f; [SerializeField] private LayerMask whatIsGround; public bool Grounded() { if(Physics2D.Raycast(GroundCheck.position, Vector2.down, groundCheckY, whatIsGround) || Physics2D.Raycast(GroundCheck.position + new Vector3(groundCheckX, 0, 0), Vector2.down, groundCheckY, whatIsGround) || Physics2D.Raycast(GroundCheck.position + new Vector3(-groundCheckX, 0, 0), Vector2.down, groundCheckY, whatIsGround)) { print("Player is grounded"); return true; } else { print("Player is NOT grounded"); return false; } } void Jump() { if(Input.GetButtonDown("Jump") && rb.velocity.y > 0) { rb.velocity = new Vector2(rb.velocity.x, 0); } if (Input.GetButtonDown("Jump") && Grounded()) { rb.velocity = new Vector3(rb.velocity.x, jumpForce); } } }
March 30, 2025 at 8:09 pm #17672::Remove this part in your code and see if the “1-second delay to jump again” issue still happens.
void Jump() {
if(Input.GetButtonDown("Jump") && rb.velocity.y > 0) { rb.velocity = new Vector2(rb.velocity.x, 0); }if (Input.GetButtonDown("Jump") && Grounded()) { rb.velocity = new Vector3(rb.velocity.x, jumpForce); } }The reason you can jump after about 1 second is because the removed code allows you to jump when your Y-velocity is less than 0, i.e. when you start falling downwards.
March 31, 2025 at 2:47 am #17678::Yes, it still persists. Now I just can’t let go of the keyboard to cancel the jump. Weird, from what you said it should have stopped the delay due to that part of the code because of the Y-Velocity.
March 31, 2025 at 5:05 am #17681::Have you checked your What Is Ground to see if the correct layers are checked?
And have you checked if your ground GameObjects are all assigned to the layers under What Is Ground?
March 31, 2025 at 5:15 am #17684::Yes both Grounds and Player is set to
Layer 3: Ground
and Player is set to thewhatIsGround
variableGround
March 31, 2025 at 5:16 am #17686::Great! Since both the ground and player are set correctly to the
Ground
layer, let’s delve a bit deeper into the issue. Here are some additional troubleshooting steps and adjustments you can try:-
Check Raycast Hit: Add a debug statement to see if the raycasts are actually hitting the ground. This can help determine if the
GroundCheck
is functioning as expected.public bool Grounded() { RaycastHit2D hit = Physics2D.Raycast(GroundCheck.position, Vector2.down, groundCheckY, whatIsGround); RaycastHit2D hitRight = Physics2D.Raycast(GroundCheck.position + new Vector3(groundCheckX, 0, 0), Vector2.down, groundCheckY, whatIsGround); RaycastHit2D hitLeft = Physics2D.Raycast(GroundCheck.position + new Vector3(-groundCheckX, 0, 0), Vector2.down, groundCheckY, whatIsGround); bool isGrounded = hit || hitRight || hitLeft; Debug.Log("Grounded: " + isGrounded); return isGrounded; }
-
Check for Multiple Jump States: Ensure that you don’t have any other scripts or logic that might be allowing the character to jump again while in the air. Sometimes, other scripts might interfere with the jumping logic.
-
Physics Settings: Check if there are any physics settings in Unity that might affect how raycasting works, like the
Collision Detection
mode on the Rigidbody. Setting it toContinuous
might help. -
Jump Cooldown: To prevent jumping immediately after landing, consider implementing a cooldown mechanism after a jump. This can help ensure that even if the method is called again in quick succession, it won’t allow another jump until a certain condition is met.
private bool canJump = true; private float jumpCooldown = 0.2f; void Jump() { if (canJump && Input.GetButtonDown("Jump") && Grounded()) { rb.velocity = new Vector2(rb.velocity.x, jumpForce); StartCoroutine(JumpCooldown()); } } private IEnumerator JumpCooldown() { canJump = false; yield return new WaitForSeconds(jumpCooldown); canJump = true; }
-
Visual Debugging: Use Gizmos to visualize your raycasts in the scene view. This can help you see if they are aligned correctly with the ground.
void OnDrawGizmos() { Gizmos.color = Color.red; Gizmos.DrawLine(GroundCheck.position, GroundCheck.position + Vector2.down * groundCheckY); Gizmos.DrawLine(GroundCheck.position + new Vector3(groundCheckX, 0, 0), GroundCheck.position + new Vector3(groundCheckX, 0, 0) + Vector2.down * groundCheckY); Gizmos.DrawLine(GroundCheck.position + new Vector3(-groundCheckX, 0, 0), GroundCheck.position + new Vector3(-groundCheckX, 0, 0) + Vector2.down * groundCheckY); }
Try implementing these suggestions and see if they help resolve the issue with the jumping behavior. Let me know how it goes!
March 31, 2025 at 4:55 pm #17712::@doctorfrostbloom can you try the suggestions Ser Apustaja has and let me know if it works?
April 1, 2025 at 7:08 am #17733::Hm, there still seems to be an error. Changing the Player’s
Collision Detection
toContinuous
seemed to do the trick as well as copying the code Ser Apustaja wrote, but all it seemed to do was slightly increase the delay to maybe two seconds. I even tried moving the Ground Check to below the player to see if the issue was it was confusing the player itself as ground, but that wasn’t the case. I feel like I got a little closer to fixing it, but something is still wrong.April 1, 2025 at 7:11 am #17734::It sounds like you’re making progress, but let’s dig a little deeper to identify the root cause of the jumping issue. Here are some additional steps and suggestions that could help:
-
Check Rigidbody Settings: Ensure that your Rigidbody2D settings are properly configured. The
Gravity Scale
should be set to a value that allows for realistic jumping and falling (typically around1
), and ensure that theMass
is set appropriately to allow for the character to respond to physics correctly. -
GroundCheck Positioning: Make sure the
GroundCheck
object is positioned correctly relative to the player’s collider. Sometimes, if theGroundCheck
is too far from the player or if the collider is not set properly, it can cause issues with detecting ground. -
Debugging Raycast Hits: Since you have already added logging for whether the player is grounded, try logging the results of each individual raycast to see if they are detecting the ground correctly. This can help identify if one of the raycasts is failing:
public bool Grounded() { RaycastHit2D hit = Physics2D.Raycast(GroundCheck.position, Vector2.down, groundCheckY, whatIsGround); RaycastHit2D hitRight = Physics2D.Raycast(GroundCheck.position + new Vector3(groundCheckX, 0, 0), Vector2.down, groundCheckY, whatIsGround); RaycastHit2D hitLeft = Physics2D.Raycast(GroundCheck.position + new Vector3(-groundCheckX, 0, 0), Vector2.down, groundCheckY, whatIsGround); bool isGrounded = hit || hitRight || hitLeft; Debug.Log("Hit: " + hit.collider + " | Hit Right: " + hitRight.collider + " | Hit Left: " + hitLeft.collider); Debug.Log("Grounded: " + isGrounded); return isGrounded; }
-
Adjust Ground Check Distance: Experiment with increasing the
groundCheckY
distance to see if rays are reaching the ground. Sometimes increasing this value can help improve detection. -
Multiple Ground Checks: If your character is jumping too soon after landing, consider adding a
grounded
state that can only be switched back after a short delay when the player lands. This would effectively prevent the player from jumping again until they are fully grounded. -
Physics Materials: Check if the player or ground objects are using any physics materials that might affect interaction, such as bounciness or friction. These can sometimes cause unexpected behavior.
-
Time Between Jumps: If you want a delay between jumps, you could also enforce a minimum time before allowing another jump:
private float jumpCooldownTime = 0.2f; private float lastJumpTime; void Jump() { if (Input.GetButtonDown("Jump") && Grounded() && Time.time >= lastJumpTime + jumpCooldownTime) { rb.velocity = new Vector2(rb.velocity.x, jumpForce); lastJumpTime = Time.time; } }
-
Layer Collision Matrix: Double-check the physics layer collision matrix in Unity’s project settings to ensure the layers are set to collide properly.
Try these suggestions, and see if they help resolve the jumping issue. If you continue to have problems, providing additional context or code snippets might help zero in on the problem!
April 1, 2025 at 12:26 pm #17735::@doctorfrostbloom can you share a download link for your project? Either on GitHub or in Google Drive, and I will have a look at it for you.
-
-
AuthorPosts
- You must be logged in to reply to this topic.
Advertisement below: