How to Jump From A Ladder?

Hi I tried to make my character jumping while is on a lader but thats not working. I find only one way when is able to jump touching a ladder Layer but i may have to disable climbing method.
sH3


So if im disable ClimLadder in update then i can jump while character is touching a ladder layer but is not climbing on lader anymore. How could i fix it ??

Hi olsz12,

Welcome to our community! :slight_smile:

First of all, try to reenact the logic of Rick’s game. At some point, he overrides the velocity with a value that does not take other changes into consideration. If you change that line so it does not override the “other” velocity value but adds to it, you will be able to make your player jump while climbing.

Hopefully, this helped.


See also:

I’m also having this issue. The logic is easy to set up we can just change:

if (!myCollider.IsTouchingLayers(LayerMask.GetMask("Ground"))) { return; }
to
if (!myCollider.IsTouchingLayers(LayerMask.GetMask("Ground")) && !myCollider.IsTouchingLayers(LayerMask.GetMask("Climbing"))) { return; }

the issue that arises is that we set the climbVelocity every frame that we’re touching the ladder so as soon as we jump it sets the y velocity to moveInput.y. So I’m thinking we need to create an if isJumping bool and don’t update the velocity if they are jumping and return it the bool to false when they hit the ground.

Currently I have it working where you can jump off the ladder but if you land back on the ladder there are some issues. I’ll work on this bug and try to update with a fix =]

Edit:
Updated the script so that it works, let me know what you think!

ps. you have to “grab the ladder” (press w or d) after a jump which I think is a neat feature and adds flexibility to movement!

second bug found: if you jump into a ladder it acts as kind of an escalator and shoots you upwards. I am currently confused and will pretend this is a speed running feature until I figure out how to fix it :sweat_smile:

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem;

public class PlayerMovement : MonoBehaviour
{
    [SerializeField] float runSpeed = 5f;
    [SerializeField] float climbSpeed = 5f;
    [SerializeField] float jumpVelocity = 5f;
    [SerializeField] CapsuleCollider2D myCollider;

    Vector2 moveInput;
    Rigidbody2D myRigidbody;
    Animator myAnimator;
    float gravity;
    float gravityMultiplier;
    bool isJumping;


    private void Start()
    {
        myAnimator = GetComponent<Animator>();
        myRigidbody = GetComponent<Rigidbody2D>();
        gravity = myRigidbody.gravityScale;
    }

    void Update()
    {
        Run();
        FlipSprite();
        ClimbLadder();
    }

    private void FlipSprite()
    {
        if (Mathf.Abs(myRigidbody.velocity.x) < Mathf.Epsilon)
        {
            myAnimator.SetBool("isRunning", false);
            return;
        }
        myAnimator.SetBool("isRunning", true);
        transform.localScale = new Vector2(Mathf.Sign(myRigidbody.velocity.x), 1f);
    }

    private void OnJump(InputValue value)
    {

        if (!myCollider.IsTouchingLayers(LayerMask.GetMask("Ground")) && !myCollider.IsTouchingLayers(LayerMask.GetMask("Climbing")))
        {
            return;
        }

        if (value.isPressed)
        {
            isJumping = true;
            myRigidbody.velocity += new Vector2(0f, jumpVelocity);
        }
    }

    private void Run()
    {
        Vector2 playerVelocity = new Vector2(moveInput.x * runSpeed, myRigidbody.velocity.y);
        myRigidbody.velocity = playerVelocity;
    }

    void OnMove(InputValue value)
    {
        moveInput = value.Get<Vector2>();
        if (myRigidbody.velocity.y < Mathf.Epsilon)
        {
            isJumping = false;
        }
        // Debug.Log(moveInput);
    }

    void ClimbLadder()
    {

        if (!myCollider.IsTouchingLayers(LayerMask.GetMask("Climbing")))
        {
            myAnimator.SetBool("isClimbing", false);
            gravityMultiplier = 1f;
            myRigidbody.gravityScale = gravity * gravityMultiplier;
            return;
        }
        if (Mathf.Abs(myRigidbody.velocity.y) > Mathf.Epsilon)
        {
            myAnimator.SetBool("isClimbing", true);
        }
        else { myAnimator.SetBool("isClimbing", false); }

        gravityMultiplier = 0f;
        myRigidbody.gravityScale = gravity * gravityMultiplier;
        Vector2 climbVelocity = new Vector2(myRigidbody.velocity.x, moveInput.y * climbSpeed);


        if (!isJumping)
        {
            myRigidbody.velocity = climbVelocity;
        }
        else
        {
            myAnimator.SetBool("isClimbing", false);
        }

    }
}

Good job so far! I’m sure you’ll be able to fix the remaining problem as well. Add Debug.Logs to figure out what exactly is going on. The issue is very likely the velocity.

If everything else works as expected, you could clamp the speed (magnitude of the velocity vector). For reasons of performance, I’d recommend to use the sqrMagnitude. If the sqrMagnitude is higher than the squared maxSpeed (which you define), you could normalise your vector and multiply the normalised vector with maxSpeed. It might sound a bit complicated but check the Vector3 struct in the API. You’ll find everything I mentioned there.

You’re right the climbVelocity is getting updated multiple times when you jump onto the ladder. Unfortunately I don’t have time to play with this more but I’ll come back to it! I’m actually warming up for a game jam and going over basics to make sure I remember how to do everything. The jam starts tomorrow so I’ll have to move on for now.

edit: I’ll definitely look into sqrMagnitude though, thank you so much for the suggestion!

Good luck with the game jam! :slight_smile:

This topic was automatically closed after 2 days. New replies are no longer allowed.

Privacy & Terms