How would you go around making something detect the ground only?

(This is referring to 2D, Not 3D.)
I’ve been sitting for an hour or two trying to think of a workaround to this issue I have. I have viewed many videos and discussions on similar matters but none talk about this dilemma i’m having and i’ve only seen it rarely brought up but never answered. :thinking:

My issue is this: I have a movement system created allowing me to walk and jump. all of this works. great!

After running it, i realised that the player was able to jump infinitely. No big issue, I made the platforms assigned to a seperate layer then changed the script so the player can only jump if they’re touching an object on that specific layer. this worked. Great!

However, I noticed that when the player comes across a wall, since the wall counts as being on the “ground” layer, the collider thinks the player is still on the floor, thus allowing the player to jump infinitely as long as they touch the wall. that’s not good.

Ok… I thought “I could just make the walls on a seperate layer like what I did with the floor” and while this sounds plausible that means that the player can no longer jump on top of them, If I make a wall jump then make the player land on top of one of the walls (as in on the vector2(0,1) axis) then they can’t jump because the collider is touching the wall layermask. not the ground layermask. I was also unsure of how this could affect preformance and workflow so I was a bit hesitant on the idea.

So I thought to myself about possible ways I could detect the player touching the ground. I came up with an idea of raycasts then looked it up. I had discovered how to use raycasts. While this knowledge can be useful in the future it didn’t help me in my current scenario.

While yes, since the raycast is just a beam that can pass downwards,meaning that it solves the previous issue, this also means that due to the positioning, the player will be unable to stand on edges as the raycast would pass down. I thought about giving the beam an offset, changing its position or making more, but none seemed to work in theory due to general logic being applied to the ideas.

Looking further, I had discovered boxcasts, they fix the issue with raycasts as they are a box. However now i’ve just realised that I’m back at square one since the boxcast will pick up the wall as well. And if I reduce the size of the box then it will not pick up slopes. so now after a few hours i’m here looking for help. The only next solution I can think of is having the boxcast detect multiple faces and only allowing the player to jump if one of those faces have a normal of vector2(0,1).

This would solve my issue, As if the boxcollider touches the wall and the floor, it can read both faces and allow the player to jump since it’s touching a face that’s letting them touch the positive y axis of it. however, I have not found a way to implement what I had just described. I saw GetContacts but I do not know how to use that and I’d like to know if there’s a way that would be less heavy on preformance since checking for what the player is colliding with every frame does indeed sound impactful on preformance in some shape or form

This is my first unity project! And I like the small progress i’ve made so far :slightly_smiling_face:, I’d love to get help on this issue or possibly a preformance light method of getting around this issue

TL;DR:
How would I allow a player object to detect theirself touching the floor while:
A - Ignoring walls registering as the player touching the floor. because the walls aren’t floors.
B -not reducing the size of ray/box casts because they need to be wide enough to work on slopes.
C - Keeping it preformance light, I’ve been told that it’s great to learn about managing preformance early in the game making process

I’m sure i’m overthinking this whole problem, but i’m just writing here to make sure and hopefully be a source area for this issue since I spent quite sometime looking for it.

Unless I’m missing something, you’ve only been using the Layer system and not the Tag system, correct?
If so the answer is quite simple, only set the the ground / floor platform tag to ‘Ground’ and then use the following code:

    private void OnCollisionEnter2D(Collision2D collision)
    {
        if (collision.gameObject.CompareTag("Ground"))
        {
            //Enter wanted logic here
        }
    }

As for the wall, you can just set the wall’s tag to “Wall” - and add a whole different logic for:
if (collision.gameObject.CompareTag("Wall"))

As for a simple and quick doublejump upon wall once be able to stand on top of it, you can always create a prefab for ‘climbable walls’ and have an empty object that includes both a wall object and a ground object on top of it, that way once you’ll stand on the ‘wall’ you’ll actually stand on a new ground.

Hope that helps :slight_smile: