TileVania adding swim option that creates a bug in ClimbingLadder

  1. Hi I wanted to add a swimming method with a simple code but it resulted in making me slide off the ladder:D(I think the gravity 0f for some reason stopped working in ClimbLadder() I have no idea why this is happening, can somebody explain this to me? Here is the code(the only change is the Swim() and swimingSpeed variable.
  2. I can’t jump from the ladder even though after I add its mask to the condition in CheckForTheGround(), maybe can you give some hint?
using System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.InputSystem;

public class PlayerMovement : MonoBehaviour
{
    Rigidbody2D myRigidbody;
    Vector2 moveInput;
    Animator animator;
    BoxCollider2D myBoxCollider;
    CapsuleCollider2D myCapsuleCollider;
    SpriteRenderer mySpriteRenderer;
    [SerializeField] Color deathColor = new Color(0.75f, 0.25f, 0.25f, 1f);
    [SerializeField] float moveSpeed = 5f;
    [SerializeField] float jumpHeight = 15f;
    [SerializeField] float climbingSpeed = 5f;
    [SerializeField] float coyoteTime = 0.1f;
    [SerializeField] float swimingSpeed = 3f;
    [SerializeField] Vector2 deathKick = new Vector2(0f, 15f);
    bool isGrounded;
    bool isAlive = true;
    float coyoteTimeCounter;
    float myRigidbodyGravityAtStart;
    void Start()
    {
        mySpriteRenderer = GetComponent<SpriteRenderer>();
        myCapsuleCollider = GetComponent<CapsuleCollider2D>();
        myBoxCollider = GetComponent<BoxCollider2D>();
        myRigidbody = GetComponent<Rigidbody2D>();
        animator = GetComponent<Animator>();
        myRigidbodyGravityAtStart = myRigidbody.gravityScale;
    }

    void Update()
    {
        Die();
        if (isAlive)
        {
            Run();
            FlipSprite();
            ClimbLadder();
            Swim();
        }
    }
    private void FixedUpdate()
    {
        CheckForGround();
    }
    void OnMove(InputValue value)
    {
        moveInput = value.Get<Vector2>();
        Debug.Log(moveInput);
    }
    void OnJump(InputValue value)
    {
        if (!isAlive) { return; }
        if (value.isPressed)
        {
            if (isGrounded || coyoteTimeCounter > 0f)
            {
                Jump();
                coyoteTimeCounter = 0f;
            }
        }
    }


    void Jump()
    {
        myRigidbody.velocity += new Vector2(0f, jumpHeight);
    }
    void CheckForGround()
    {
        isGrounded = myBoxCollider.IsTouchingLayers(LayerMask.GetMask("Ground", "Climbing"));
        if (isGrounded && coyoteTimeCounter < 0f)
        {
            coyoteTimeCounter = coyoteTime;
        }
        else
        {
            coyoteTimeCounter -= Time.fixedDeltaTime;
        }
    }
    void Run()
    {
        Vector2 playerVelocity = new Vector2(moveInput.x * moveSpeed, myRigidbody.velocity.y);
        myRigidbody.velocity = playerVelocity;

    }
    void FlipSprite()
    {
        bool playerHasHorizontalSpeed = Mathf.Abs(myRigidbody.velocity.x) > Mathf.Epsilon;
        if (playerHasHorizontalSpeed)
        {
            transform.localScale = new Vector2(Mathf.Sign(myRigidbody.velocity.x), 1f);
            animator.SetBool("isRunning", true);
        }
        else
        {
            animator.SetBool("isRunning", false);
        }
    }
    void ClimbLadder()
    {
        if (!myBoxCollider.IsTouchingLayers(LayerMask.GetMask("Climbing")))
        {
            myRigidbody.gravityScale = myRigidbodyGravityAtStart;
            animator.SetBool("isClimbing", false);
            return;
        }

        Vector2 climbingVelocity = new Vector2(moveInput.x * moveSpeed, moveInput.y * climbingSpeed);
        myRigidbody.velocity = climbingVelocity;
        myRigidbody.gravityScale = 0f;
        bool playerHasVerticalSpeed = Mathf.Abs(myRigidbody.velocity.y) > Mathf.Epsilon;
        animator.SetBool("isClimbing", playerHasVerticalSpeed);


    }
    void Die()
    {
        if (myCapsuleCollider.IsTouchingLayers(LayerMask.GetMask("Enemy", "Hazards")))
        {
            isAlive = false;
            animator.SetTrigger("Die");
            mySpriteRenderer.color = deathColor;
            myRigidbody.velocity += deathKick;
            myBoxCollider.enabled = false;
            myCapsuleCollider.enabled = false;
        }
    }
    void Swim()
    {
        if (!myBoxCollider.IsTouchingLayers(LayerMask.GetMask("Water")))
        {
            myRigidbody.gravityScale = myRigidbodyGravityAtStart;            
            return;
        }

        Vector2 swimingVelocity = new Vector2(moveInput.x * swimingSpeed, moveInput.y * swimingSpeed);
        myRigidbody.velocity = swimingVelocity;
        myRigidbody.gravityScale = 0.5f;
    }

}

Hi xSerj,

It’s great to see that you are challenging yourself. :slight_smile:

Have you already tried to add Debug.Logs to your code to see what is going on during runtime? Maybe your code does not do what you expect it to do.

Hello @xSerj,

I can’t spot mistake in a code. But if I remember correctly, when you create a level you “paint” different tiles in different levels, have you checked that your ladders are in a climbing an not in a water level for example?
I know I had some issue with ladders too and then I spot that some of those were in different layer, than they should be.

Hi yes my ladders are in climbing layer and the water is in water layer. Also there is a problem that i cannot jump from the ladder even though the layer “Climbing is added to the CheckForGround()”, here’s my repository if you’d like to see: https://github.com/xSerj111/Unity-Course-TileVania

Privacy & Terms