-1

I'm learning to use Unity Engine and I've been working on the basis for a 2D platformer, and having a problem with the player character being able to jump indefinitely.

I've created an UniversalMovementHandler class for the handling all movement common to both the player and other characters in the game (which I still haven't implemented) and a PlayerControlls script for checking for user input, both are attached to the Player prefab that is spawned by the checkpoint

UniversalMovementHandler.cs:

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

public class UniversalMovementHandler: MonoBehaviour
{
    public Rigidbody2D rb;

    // Rigidbody setup
    void Start ()
    {
        rb = transform.GetComponent <Rigidbody2D> ();
    }

    // Check if object is on the ground with a raycast
    private bool IsGrounded ()
    {
        // Layermask setup
        LayerMask MaskA = LayerMask.GetMask ("Character");
        LayerMask MaskB = LayerMask.GetMask ("Ignore Raycast");
        LayerMask Mask = MaskA | MaskB;


        // Raycating
        RaycastHit2D hit = Physics2D.Raycast (transform.position, Vector2.down, Mathf.Infinity, Mask);
        if (hit.collider != null)
        {
            float Distance = Mathf.Abs (hit.point.y - transform.position.y);
            Debug.Log ("Distance = " + Distance);
            if (Distance < transform.localScale.y / 2 + 0.1)
            {
                return true;
            }
            else
            {
                return false;
            }
        }
        else
        {
            return false;
        }
    }

    // [...]

    // Jump if grounded or can double jump
    public void Jump (float JumpForce, bool CanAirJump = false)
    {
        if (CanAirJump || IsGrounded ())
        {
            rb.AddForce (Vector2.up * JumpForce);
        }
    }
}

PlayerControlls.cs

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

public class PlayerControlls : MonoBehaviour
{
    [SerializeField] private UniversalMovementHandler MovementHandler;
    [SerializeField] private float WalkSpeed = 3;
    [SerializeField] private float WalkForce = 4;
    [SerializeField] private float JumpForce = 4;

    // UniversalMovementHandler setup
    void Start ()
    {
        MovementHandler = GameObject.Find ("Player(Clone)").GetComponent <UniversalMovementHandler> ();
        if (MovementHandler == null)
        {
            Debug.Log ("Failed to assign MovementHandler");
            Debug.Break ();
        }
    }

    // Controll handling
    void Update ()
    {
        // [...]

        if (Input.GetKeyDown (KeyCode.Space))
        {
            MovementHandler.Jump (JumpForce);
        }
    }
}

I've created three layers, 0: Default, for the ground and other colliders the player directly interacts with, 2: Ignore Raycast for checkpoints and other objects with trigger colliders and 3: Character for both the player character and NPCs. I expected the player not to be able to jump mid-air, being CanAirJump set to false, but this isn't the case, the player just flies in the air so long as you keep pressing the jump button.

Tried flipping the bits myself, setting int MaskA and int MaskB to 1 << 2 and 1 << 3, but still get the same result, printing Distance to the console returns 0, so the raycast isn't ignoring the Character layer.

I could set the player to be grounded until it jumps, but that would allow it to jump after running off the edge of a platform, also I would have other it have other movement abilities, some of which might get it off the ground.

I could check if it is in contact with a ground collider, but that would require me to setup multiple colliders for the sides of platforms to avoid jumping when in mid-air contact with the side of a platform, which seems to be overly complicated, still would this be the better option or should I try and fix the raycasting?

LSD_Sumus
  • 1
  • 4
  • In IsGrounded() it looks like you're raycasting towards the Character mask, and the Ignore Raycast mask. That would mean it does not include anything that is ground, correct? So I would assume it will keep hitting the character at a distance of 0, allowing it to jump indefinitely – FlawlessHappiness Aug 14 '23 at 09:13

0 Answers0