Search Unity

Resolved How to Jump While Climbing a Ladder in 2D

Discussion in 'Scripting' started by michaelpynes, May 23, 2022.

  1. michaelpynes

    michaelpynes

    Joined:
    Sep 12, 2019
    Posts:
    79
    So I've been working for hours trying to get this to work. Basically, I'm controlling a 2d character's velocity and while on a ladder, their velocity is the yInput * climbingSpeed else; it's just the y velocity. Jumping is being handled by setting the y velocity to "jumpForce". The issue with everything is that the character doesn't jump when I'm either touch the ladder nor actively climbing.

    This is where the normal movement and climbing movement is done.
    P.S. ApplyMovement() is called in FixedUpdate()
    Code (CSharp):
    1. void ApplyMovement()
    2.     {
    3.         float crouch = (isCrouching) ? crouchMultiplier : 1f;
    4.         float run = 1;
    5.         //float run = (Input.GetKey(KeyCode.LeftControl)) ? runMultiplier : 1f;  //Sprinting Value
    6.        //checks if touching ladder
    7.         if (Physics2D.OverlapCircle(groundCheck.position, GroundedRadius, whatIsClimbable)) { isClimbing = true; rb.gravityScale = 0f; }
    8.         else { isClimbing = false; rb.gravityScale = 3.5f; }
    9.  
    10.         //Adding Force Horizontally (no Slope detected) and when not jumping nor pillarJumping
    11.         if (Physics2D.OverlapCircle(groundCheck.position, GroundedRadius, whatIsGround) && !isOnSlope &&/* !isJumping && */!isPillarJumping)
    12.         {
    13.             //jumpForce = 1f;
    14.             isJumping = false;
    15.             //performedJump = false;
    16.             movement.Set(movement.x + groundedspeed * xInput * crouch * run * slowMultiplier,
    17.                 isClimbing ? (yInput * climbingSpeed) : rb.velocity.y);
    18.             movement.x *= (1 - groundedDamp);
    19.            
    20.         }
    21.         //Adding Force towards Slope's direction (when Slope detected)
    22.         /*else if (Physics2D.OverlapCircle(groundCheck.position, GroundedRadius, whatIsGround) && isOnSlope && canWalkOnSlope && !isJumping && !isPillarJumping)
    23.         *{
    24.         *    movement.Set(movement.x + groundedspeed * slopeNormalPerp.x * -xInput * crouch * run * slowMultiplier,
    25.         *        movement.y + groundedspeed * slopeNormalPerp.y * -xInput * crouch * run * slowMultiplier);
    26.         *    movement *= (1 - groundedDamp);
    27.         *    rb.velocity = movement;
    28.         }*/
    29.         //Adding Force Horizontally and Mid-air Speed Multiplier
    30.         else {//gets here when holding jump before release
    31.             movement.Set(movement.x + midairspeed * xInput * crouch * run * slowMultiplier,
    32.                 isClimbing ? (yInput * climbingSpeed) : rb.velocity.y);
    33.             movement.x *= (1 - midairDamp);
    34.         }
    35.         rb.velocity = movement;
    36.     }


    This is where the values for jumping are done when the player presses jump
    Code (CSharp):
    1.     public void pressedJump(InputAction.CallbackContext obj)
    2.     {
    3.         jumpForce = 17f;
    4.         ActivateJumpValues();
    5.     }
    Code (CSharp):
    1. public void ActivateJumpValues()//InputAction.CallbackContext obj)
    2.     {
    3.         if (!performedJump)
    4.         {
    5.             CatchMissedTimer = CatchMissedDuration;
    6.             performedJump = true;
    7.             //isJumping = false;
    8.         }
    9.     }


    This is where the jumping is actually done when the player releases jump
    Code (CSharp):
    1. public void releasedJump(InputAction.CallbackContext obj)
    2.     {
    3.         //jumpForce = 1f;
    4.         DoJump();
    5.     }
    Code (CSharp):
    1. public void DoJump()//InputAction.CallbackContext obj)
    2.     {
    3.         if(!isPillarJumping) rb.velocity = new Vector2(rb.velocity.x, Mathf.Clamp(rb.velocity.y, -Mathf.Infinity, jumpReleaseClamp));
    4.         //CatchMissedTimer : the timer of the space input to stay registered (to register a jump when player is accidently pressing space before landing
    5.         //CoyoteTimer : the timer of grounded to stay registered (to avoid player pressed jump after walking off a cliff)
    6.         if (CatchMissedTimer > 0) CatchMissedTimer -= Time.deltaTime;
    7.         if (CatchMissedTimer > 0 && CoyoteTimer > 0 && !isPillarJumping)
    8.         {
    9.             isJumping = true;
    10.             //CatchMissedTimer = CatchMissedDuration;
    11.             CoyoteTimer = 0f;
    12.             rb.velocity = new Vector2(rb.velocity.x, jumpForce);
    13.             performedJump = false;
    14.         }
    15.     }
     
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,674
    Some of the problem comes from the contradictions between jumping and laddering.

    Usually ladders are auto-mount: eg, you get close enough (collider or trigger or rect overlap) and press up or down, the game infers you are on the ladder and should be acting in a ladder-y way. Some games require you to hit a button to "connect" to the ladder.

    When you jump from a ladder, technically you are still overlapping the ladder, so you need some kind of inhibition from considering reattaching to that ladder, assuming you would auto-ladder. Like what if you jump straight up? Does it instantly reattach at the next rung? Or wait until you're descending then reattach? Or stay permanently detached?

    What if you have air-control of your jump and change your mind to come back to to the ladder? It should attach, right? Or should it only attach to a ladder when you start by walking onto it from a platform?

    Every one of these are going to be substantially-different state diagrams.

    You're welcome to look at my ladder code... you can NOT jump off the ladder (you can step off it though), but you CAN jump onto the ladder. Look for the
    DemoClimbLadder2D
    scene here:

    proximity_buttons is presently hosted at these locations:

    https://bitbucket.org/kurtdekker/proximity_buttons

    https://github.com/kurtdekker/proximity_buttons

    https://gitlab.com/kurtdekker/proximity_buttons

    https://sourceforge.net/projects/proximity-buttons/
     
  3. michaelpynes

    michaelpynes

    Joined:
    Sep 12, 2019
    Posts:
    79
    The thing about it is that the game is meant to be a fast paced platformer. So the intended way that I want the ladder to work is instantly be able to climb when you're touching it, if you jump while on the ladder, you go a bit higher up on it; if you are at the very top of the ladder, you do a normal jump.
     
  4. michaelpynes

    michaelpynes

    Joined:
    Sep 12, 2019
    Posts:
    79
    I solved the issue, I used a short-hand if/else statement in the "movement.set" function so that if isClimbing=true the player would move based on jumpForce+movement.x else, they would just move normally.