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

Viewing 15 posts - 1 through 15 (of 17 total)
  • Author
    Posts
  • #17644
    Terence
    Level 30
    Keymaster
    Helpful?
    Up
    0
    ::

    @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)

    #17645
    Ser Apustaja
    Level 5
    AI Assistant
    (BETA)
    Helpful?
    Up
    0
    ::

    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:

    1. 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.

    2. 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.

    3. 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.

    4. 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.

    5. 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;
       }
    6. Check for Other Scripts: Ensure that there aren’t any other scripts affecting the jump behavior or modifying the Rigidbody’s velocity unexpectedly.

    7. 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!

    #17646
    Terence
    Level 30
    Keymaster
    Helpful?
    Up
    0
    ::

    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;
        }
    }
    #17649
    Doctor Frostbloom
    Level 3
    Participant
    Helpful?
    Up
    0
    ::

    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.

    #17655
    Terence
    Level 30
    Keymaster
    Helpful?
    Up
    0
    ::

    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);
        }
    }
    #17656
    Doctor Frostbloom
    Level 3
    Participant
    Helpful?
    Up
    0
    ::

    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);
        }
    }
    }
    #17672
    Terence
    Level 30
    Keymaster
    Helpful?
    Up
    0
    ::

    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.

    #17678
    Doctor Frostbloom
    Level 3
    Participant
    Helpful?
    Up
    0
    ::

    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.

    #17681
    Terence
    Level 30
    Keymaster
    Helpful?
    Up
    0
    ::

    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?

    #17684
    Doctor Frostbloom
    Level 3
    Participant
    Helpful?
    Up
    0
    ::

    Yes both Grounds and Player is set to Layer 3: Ground and Player is set to the whatIsGround variable Ground

    #17686
    Ser Apustaja
    Level 5
    AI Assistant
    (BETA)
    Helpful?
    Up
    0
    ::

    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:

    1. 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;
       }
    2. 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.

    3. 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 to Continuous might help.

    4. 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;
       }
    5. 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!

    #17712
    Terence
    Level 30
    Keymaster
    Helpful?
    Up
    0
    ::

    @doctorfrostbloom can you try the suggestions Ser Apustaja has and let me know if it works?

    #17733
    Doctor Frostbloom
    Level 3
    Participant
    Helpful?
    Up
    0
    ::

    Hm, there still seems to be an error. Changing the Player’s Collision Detection to Continuous 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.

    #17734
    Ser Apustaja
    Level 5
    AI Assistant
    (BETA)
    Helpful?
    Up
    0
    ::

    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:

    1. 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 around 1), and ensure that the Mass is set appropriately to allow for the character to respond to physics correctly.

    2. GroundCheck Positioning: Make sure the GroundCheck object is positioned correctly relative to the player’s collider. Sometimes, if the GroundCheck is too far from the player or if the collider is not set properly, it can cause issues with detecting ground.

    3. 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;
       }
    4. 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.

    5. 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.

    6. 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.

    7. 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;
           }
       }
    8. 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!

    #17735
    Terence
    Level 30
    Keymaster
    Helpful?
    Up
    0
    ::

    @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.

Viewing 15 posts - 1 through 15 (of 17 total)
  • You must be logged in to reply to this topic.

Go to Login Page →


Advertisement below: