I managed to solve all the bugs and jump on the ladder. The script I’m copy-pasting is not refactored, I’ll leave that up to you.
With this script, you’ll be able to jump on ladders but the jump will be “canceled” when the character starts to fall, that happens only when touching the ladders, if the character isn’t touching them it will fall as always.
The solution to stop the bouncing at the stop is not precisely elegant but it works, I just added a trigger collider on top of the ladder with a custom Layer called “Ladder Top”, when the character is touching that collider it will prevent the character from trying to climb, stopping that bounce.
I didn’t write any comments in the script, if you have any questions feel free to ask.
Here's the full script.
using UnityEngine;
[RequireComponent(typeof(Rigidbody2D))]
[RequireComponent(typeof(Collider2D))]
public class Move : MonoBehaviour
{
[SerializeField] float speed = 0;
[SerializeField] LayerMask jumpLayer = 0;
[SerializeField] float jumpForce = 0;
[SerializeField] LayerMask ladderLayer = 0;
[SerializeField] LayerMask ladderTopLayer = 0;
bool canJump;
bool isJumping;
bool canClimb;
float hAxis;
float vAxis;
Collider2D col;
Rigidbody2D rg2D;
private void Awake()
{
rg2D = GetComponent<Rigidbody2D>();
col = GetComponent<Collider2D>();
}
void Update()
{
hAxis = Input.GetAxisRaw("Horizontal");
vAxis = col.IsTouchingLayers(ladderTopLayer) && Input.GetAxisRaw("Vertical") > 0 ? 0 : Input.GetAxisRaw("Vertical");
if (canJump && Input.GetButtonDown("Jump"))
{
isJumping = true;
rg2D.AddForce(Vector2.up * jumpForce);
}
else if (rg2D.velocity.y < 0 || (!Mathf.Approximately(vAxis, 0) && canClimb))
{
isJumping = false;
}
}
private void FixedUpdate()
{
canJump = col.IsTouchingLayers(jumpLayer) || col.IsTouchingLayers(ladderLayer);
canClimb = col.IsTouchingLayers(ladderLayer);
rg2D.gravityScale = canClimb && !isJumping ? 0 : 1;
rg2D.velocity = GetInputVelocity();
}
private Vector2 GetInputVelocity()
{
Vector2 newVelocity = Vector2.right * hAxis * speed;
newVelocity.y = canClimb && !isJumping ? vAxis * speed : rg2D.velocity.y;
return newVelocity;
}
}
If you want, you can modify this code to make the character fall until the player presses the climb key, which might be better, because right now the ladders behaves like a very sticky wall.