Collision detection for jumping C# [SOLVED]

Hello guys
Im having a problem with my C# movement script. Everythings works so far the way i want it, but when i jump, i can jump as many times as i want (even mid air). So what im trying todo is some kind of collision detection, so when i touch any collider i can jump, if not → no jumping. I read about some people using layers, like puting the floor in a floor layer. I dont really like this idea since id have to but even crates or stones etc in this layer. Im looking for something that i wont have to tag anything (preferably, if there is no other way then nvm).
I searched trough the scripting reference for any type of function or whatever that would do that but couldnt find anything. id be happy for help and thanks in advance.
Sorry for my english, its not my native language.
Greetings Ilias

using UnityEngine;
using System.Collections;

public class moveScript : MonoBehaviour {

    public float forwardSpeed = 10f;
    public float backwardsSpeed = 5f;
    public float rotationSpeed = 70f;

    public Rigidbody rigid;
    public float jumpHeight = 10f;
    public bool isGrounded;

    void Start ()
    {
        rigid = GetComponent <Rigidbody> ();
    }

    void Update ()
    {
        //walking all directiosn
        if(Input.GetButton("e"))
        {
            transform.Translate (forwardSpeed * Time.deltaTime, 0, 0);
        }
        if(Input.GetButton("w"))
        {
            transform.Translate (0, 0, forwardSpeed * Time.deltaTime);
        }
        if(Input.GetButton("q"))
        {
            transform.Translate (-forwardSpeed * Time.deltaTime, 0, 0);
        }
        if(Input.GetButton("s"))
        {
            transform.Translate (0, 0, -backwardsSpeed * Time.deltaTime);
        }

        //rotating all directiosn
        if(Input.GetButton("d"))
        {
            transform.Rotate (0, rotationSpeed * Time.deltaTime, 0);
        }
        if(Input.GetButton("a"))
        {
            transform.Rotate (0, -rotationSpeed * Time.deltaTime, 0);
        }

        //jumping
        if (rigid.detectCollisions == true) {
            if (Input.GetButtonDown ("Jump")) {
                rigid.AddForce (Vector3.up * jumpHeight);
            }
        }
    }
}

https://unity3d.com/learn/tutorials/topics/physics/detecting-collisions-oncollisionenter
(also the other “OnCollision…” links in the “related documentation”)

thanks for the answer
I seem to get closer but something is still not right, somehow my isGrounded boolean seems to not work

using UnityEngine;
using System.Collections;

public class moveScript : MonoBehaviour {

    public float forwardSpeed = 10f;
    public float backwardsSpeed = 5f;
    public float rotationSpeed = 70f;

    private Rigidbody rigid;

    public float jumpHeight = 10f;
    public bool isGrounded;

    void Start ()
    {
        rigid = GetComponent <Rigidbody> ();
    }

    void Update ()
    {
        //walking all directions
        if(Input.GetButton("e"))
        {
            transform.Translate (forwardSpeed * Time.deltaTime, 0, 0);
        }
        if(Input.GetButton("w"))
        {
            transform.Translate (0, 0, forwardSpeed * Time.deltaTime);
        }
        if(Input.GetButton("q"))
        {
            transform.Translate (-forwardSpeed * Time.deltaTime, 0, 0);
        }
        if(Input.GetButton("s"))
        {
            transform.Translate (0, 0, -backwardsSpeed * Time.deltaTime);
        }

        //rotating left/right
        if(Input.GetButton("d"))
        {
            transform.Rotate (0, rotationSpeed * Time.deltaTime, 0);
        }
        if(Input.GetButton("a"))
        {
            transform.Rotate (0, -rotationSpeed * Time.deltaTime, 0);
        }

        //jumping
        if (isGrounded = true && Input.GetButtonDown ("Jump"))
        {
            rigid.AddForce (Vector3.up * jumpHeight);
        }           
    }

    void OnCollisionEnter (Collision collision)
    {
        isGrounded = true;
    }
    void OnCollisionExit (Collision collision)
    {
        isGrounded = false;
    }
}

Make sure that your OnCollisionEnter is being triggered. I’ve had issues with it not being reliable.
My suggestion would be to create a function that is called when the player tries to jump, that either returns a bool or changes your existing isGrounded bool, that uses a raycast to find the distance to a collider below the player.

Using OnCollisionEnter for this isn’t generally the best approach, as then any collision will allow you to jump again, even if it’s on your head. Instead what you want is a raycast or sphere-cast at your feet (and one in front of you if you want to do things like wall-grabs.

thanks for the answers, i guess ill try it with the raycast, ill post my results here once i got it working

yay it seems to work :slight_smile: thanks alot guys
tough as you will see in my script down below, im casting now a raycast all the time to check if im grounded. is this a bad way todo it? i mean i could imagine that there is a way to cast a ray only when im pressing jump, and if hes hitting something under my character then he jumps. i cant really figure out how todo this since this would make my isgrounded boolean useless, and idk how to code it without it. can anyone help me with this, if u guys think there is a better way todo this?

using UnityEngine;
using System.Collections;

public class moveScript : MonoBehaviour {

    public float forwardSpeed = 10f;
    public float backwardsSpeed = 5f;
    public float rotationSpeed = 70f;

    private Rigidbody rigid;

    public float jumpHeight = 10f;
    public bool isGrounded;
    public float feetDist = 0.1f;

    void Start ()
    {
        rigid = GetComponent <Rigidbody> ();
    }

    void Update ()
    {
        //walking all directions
        if(Input.GetButton("e"))
        {
            transform.Translate (forwardSpeed * Time.deltaTime, 0, 0);
        }
        if(Input.GetButton("w"))
        {
            transform.Translate (0, 0, forwardSpeed * Time.deltaTime);
        }
        if(Input.GetButton("q"))
        {
            transform.Translate (-forwardSpeed * Time.deltaTime, 0, 0);
        }
        if(Input.GetButton("s"))
        {
            transform.Translate (0, 0, -backwardsSpeed * Time.deltaTime);
        }

        //rotating left/right
        if(Input.GetButton("d"))
        {
            transform.Rotate (0, rotationSpeed * Time.deltaTime, 0);
        }
        if(Input.GetButton("a"))
        {
            transform.Rotate (0, -rotationSpeed * Time.deltaTime, 0);
        }

        //jumping
        if (isGrounded && Input.GetButtonDown ("Jump"))
        {
            rigid.AddForce (Vector3.up * jumpHeight);
        }          
    }

    void FixedUpdate ()
    {
        Vector3 fwd = transform.TransformDirection (Vector3.down);

        if (Physics.Raycast (transform.position, fwd, feetDist)) {
            isGrounded = true;
        }
        else
        {
            isGrounded = false;
        }
    }
}

Casting a ray every frame is perfectly fine, you could have hundreds if not thousands on modern hardware. You can put a racyast at the bottom corners and one in the center if you want more information about the slope you’re on. This is essentially how Sonic was made. So for example, you’d know if you were teetering on an edge if only one of the raycasts were being triggered. Or if all are triggered, but the front point has a higher position, then you’re heading up hill. And there’s much, much more you could do with it. Raycasts out the front(side) and up from the character can be useful as well depending on what you’re making.

Also look into RaycastNonAlloc if you really want to strive for the most performance, though it’s not a big deal unless you’re doing many dozens of them.

I’d still suggest putting your raycast for checking if grounded into it’s own function, that way it’s not being done every frame and you can call it when needed.

thanks alot for all the great answers, i think if its not as bad as i tought performance wise, then ill leave it like that for now and keep working on other important things of the game :slight_smile:
greetings ilias