Implementing jump into 2D game

Hey guys! Sorry if this is in the wrong place, I’m pretty new to these forums and I’m still trying to figure everything out. I’ve been looking for a while for a fix to this particular error, but I haven’t been able to find one.

I’ve been creating a couple of different simple 2D platformers in Unity, and I’ve noticed a problem with my current jumping code. Here’s what I have observed as happening:

  • Player hits a wall in midair
  • Game detects player collision with tilemap and that the tilemap is underneath the player.
  • Game resets the player’s jumps to their maximum jumps.
  • Player uses the jumps while touching the wall.
  • Player hits the ground without removing themselves from the wall.
  • Since the player has not exited the collision, the player does not gain back their jumps upon hitting the ground.
  • The player now has no jumps, and, depending on their current position, may be stuck and soft locked

Here’s my code to look over (I’ve removed everything not relevant to jumping, hope that works)

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

public class PlayerScript : MonoBehaviour
{
    [Header("Player Settings")]
    public float jumpForce;
    public int maxJumps;

    [Header("Components")]
    public Rigidbody2D rb;

    // private variables
    public int curJumps;

    private void Awake()
    {
        curJumps = maxJumps;
    }

    private void OnCollisionEnter2D(Collision2D collision)
    {
        if(collision.gameObject.tag == "tilemap" && collision.contacts[0].point.y < transform.position.y)
        {
            curJumps = maxJumps;

        }
    }

    private void jump()
    {
        curJumps--;
        rb.velocity = new Vector2(rb.velocity.x, 0);
        rb.AddForce(Vector2.up * jumpForce, ForceMode2D.Impulse);
    }

    public void onJumpInput(InputAction.CallbackContext context)
    {
    // called externally whenever the jump button is pressed
        if (context.phase == InputActionPhase.Performed)
        {
            if (curJumps > 0)
            {
                jump();
            }
        }
    }
}

So, what’s the best way to fix this error? I’ve tried a couple of different things, but none of them seem to work. Is there a better way to handle jumping that I should be using instead?

Some random ways:

  • use some kind of identifying marker (layer, tag, a custom MonoBehaviour, name, etc.) to mark walls as not resetting jump, then test and DON’T reset the jump when you hit them. This requires authoring ALL levels in your game appropriately

  • when you contact a collider, iterate the contact points (they are given to you in the collision argument) and decide if they are low enough on your character to count as “standing”. This lets you do it in code rather than changing all level, but it’s more work to make it “just so.”

  • have multiple colliders on your player: one in the center bottom, and ones on the sides of you. Then on collision, query which of your own colliders hit (this information is also in the collision argument) and see if it hit your toes or your sides.