SOLVED: Complete Code for Jumping on/off Ladder with Animation Changing (NO BUG)

Hi there, I am a beginner and studied only for a week up to this point, I love Rick’s class, he is so amazing and made every step so clear and easy to follow. I am an artist, and my OCD drove me to make everything visually perfect, so I have googled and youtubed a lot to solve this Ladder issue, this is the code I figured, if there any better or simpler way to write it, please let me know, thanks, hope this help! Here are some key notes:

  1. On the ladder because there is 0 Gravity while Climbing, we need to set gravity back to default while performing the jumping action, otherwise the player will keep going up;
    -first, add this under OnJump:
    if (!myFeetCollider.IsTouchingLayers(LayerMask.GetMask(“Ground”)) && !myFeetCollider.IsTouchingLayers(LayerMask.GetMask(“Climb”)))
    then return;
    -second, set gravity to default when jump is pressed on ladder,
    if (myRigidbody.velocity.y > Mathf.Epsilon && myFeetCollider.IsTouchingLayers(LayerMask.GetMask(“Climb”)))
    then {myRigidbody.gravityScale = gravityScaleAtStart;}

  2. (Then when jumping on the ladder and reaching the highest point, then the player will start falling down if gravity is the default, I want the player to catch on the ladder instead of falling back down to the ground, so I need to set the gravity to 0 when reaches the highest jump point while the platyer is touching the ladder, this will ONLY HAPPEN/NEEDED when the ladder is LONGER than the JUMP HEIGHT.)
    So this is the condition
    if (myRigidbody.velocity.y < Mathf.Epsilon && isJumping && myFeetCollider.IsTouchingLayers(LayerMask.GetMask(“Climb”)))
    (myRigidbody.velocity.y < Mathf.Epsilon ) is when speed is 0, when speed is 0 in a jump action, it means the player reaches the highest jump point and will start falling down due to gravity. that’s why we are setting gravity to 0 at this point so the player will land on the ladder.

  3. remember to reactivate the climbing input again or you might not be able to move up and down after the jump if u landed back on the ladder.

  4. For the Animation part, I make the player switch back to The Idle Animation while not moving on the Ladder, and switch to Running Animation when Jump Off the Ladder.

public class PlayerMovement : MonoBehaviour

{

[SerializeField] float runSpeed = 7f;

[SerializeField] float jumpSpeed = 20f;

[SerializeField] float climbSpeed = 4f;

   

Vector2 moveInput;

Rigidbody2D myRigidbody;

Animator myAnimator;

CapsuleCollider2D myBodyCollider;

BoxCollider2D myFeetCollider;

float gravityScaleAtStart;

bool isJumping;

//bool isClimbing;

  

void Start()

{

    myRigidbody = GetComponent<Rigidbody2D>();

    myAnimator = GetComponent<Animator>();

    myBodyCollider = GetComponent<CapsuleCollider2D>();

    myFeetCollider = GetComponent<BoxCollider2D>();

    gravityScaleAtStart = myRigidbody.gravityScale;

}

void Update()

{

    Run();

    FlipSprite();

    ClimbLadder();

    if(Mathf.Abs(myRigidbody.velocity.x) < Mathf.Epsilon)

    {

        myAnimator.SetBool("isRuning", false);

    }

   

}

void OnMove(InputValue value)

{

    moveInput = value.Get<Vector2>();

   

}

void OnJump(InputValue value)

{

    if (!myFeetCollider.IsTouchingLayers(LayerMask.GetMask("Ground")) && !myFeetCollider.IsTouchingLayers(LayerMask.GetMask("Climb")))

    {

        return;

    }

    if(value.isPressed)

    //if(Input.GetButtonDown("Jump"))

    {

        myRigidbody.velocity += new Vector2 (0f, jumpSpeed);

        isJumping = true;

        myAnimator.SetBool("isClimbing", false);

       

    }

    if(myRigidbody.velocity.y > Mathf.Epsilon && myFeetCollider.IsTouchingLayers(LayerMask.GetMask("Climb")))

    {

        myRigidbody.gravityScale = gravityScaleAtStart;

        myAnimator.SetBool("isClimbing", false);

    }

    if(myFeetCollider.IsTouchingLayers(LayerMask.GetMask("Climb")))

    {

        myAnimator.SetBool("isClimbing", true);

    }



    //if(myRigidbody.velocity.sqrMagnitude > maxSpeed * maxSpeed)

    //{

        //Vector2 movement = new Vector2 (runSpeed, jumpSpeed);

        //movement.Normalize();

        //myRigidbody.MovePosition(myRigidbody.position + movement * maxSpeed * Time.fixedDeltaTime);

        //myRigidbody.velocity = Vector2.ClampMagnitude(myRigidbody.velocity, maxSpeed);

    //}

}

        //clamp the speed (magnitude of the velocity vector).sqrMagnitude.

        //If the sqrMagnitude is higher than the squared maxSpeed (which you define),

        //normalise your vector, and multiply the normalised vector with maxSpeed.

         

void Run()



{

    Vector2 playerVelocity = new Vector2(moveInput.x * runSpeed, myRigidbody.velocity.y);

    myRigidbody.velocity = playerVelocity;

    myAnimator.SetBool("isRuning", true);

    //bool playerHasHorizontalSpeed

              

}

void FlipSprite()

{

    bool playerHasHorizontalSpeed = Mathf.Abs(myRigidbody.velocity.x) > Mathf.Epsilon;

    if (playerHasHorizontalSpeed)

    {

        transform.localScale = new Vector2 (Mathf.Sign(myRigidbody.velocity.x), 1f);

    }

}




void ClimbLadder()



{

    if (!myFeetCollider.IsTouchingLayers(LayerMask.GetMask("Climb")))

    {

        isJumping = false;

        myRigidbody.gravityScale = gravityScaleAtStart;

        myAnimator.SetBool("isClimbing", false);

        myAnimator.SetBool("isRuning", true);

        myAnimator.enabled = true;

        return;

    }

    // When exit Ladder

    if (!isJumping && myFeetCollider.IsTouchingLayers(LayerMask.GetMask("Climb")))

    {

        //isClimbing = true;

        myAnimator.SetBool("isClimbing", true);

        Vector2 climbVelocity = new Vector2(myRigidbody.velocity.x, moveInput.y * climbSpeed);

        myRigidbody.velocity = climbVelocity;

        myRigidbody.gravityScale = 0f;

    }

    // if on ladder and not jumping, then climb

    //bool playerHasVerticalSpeed = Mathf.Abs(myRigidbody.velocity.y) > Mathf.Epsilon;

    //myAnimator.enabled = true;

    //myAnimator.SetBool("isClimbing", playerHasVerticalSpeed);

    // When on ladder climbing & not jumping

    if(Mathf.Abs(myRigidbody.velocity.y) < Mathf.Epsilon)

    {

        myAnimator.SetBool("isClimbing", false);

    }

    //if(!isClimbing && myFeetCollider.IsTouchingLayers(LayerMask.GetMask("Climb")))

    //{

        //myAnimator.enabled = false;

    //}

    // Stop Animation when the player stop movement on Ladder

    if (myRigidbody.velocity.y < Mathf.Epsilon && isJumping && myFeetCollider.IsTouchingLayers(LayerMask.GetMask("Climb")))

    {

        //isClimbing = true;

        // myAnimator.SetBool("isClimbing", false);

        isJumping = false;

        Vector2 climbVelocity = new Vector2(myRigidbody.velocity.x, moveInput.y * climbSpeed);

        myRigidbody.velocity = climbVelocity;

        myRigidbody.gravityScale = 0;

    }

    // if falling in jumping action while on ladder, cancel jumping , activate climbing, set gravity to 0

   

    //if (Input.GetButton("Jump"))

    //{

        // myRigidbody.gravityScale = 0f;

        //myRigidbody.velocity += new Vector2 (0f, jumpSpeed);

        //isJumping = true;

    //}

                           

        // myRigidbody.gravityScale = gravityScaleAtStart;

   

        // myRigidbody.AddForce(transform.up * thrust);

        // myRigidbody.AddForce(transform.up * thrust, ForceMode2D.Impulse);

        // isJumping = false;

              

    //}    

}

}

3 Likes

noice code i liek eit

Privacy & Terms