Raycasing to check ground!

Hey everybody!
I have a problem with raycasting…

I wanted to fix the “bouncing” down slopes issue by pointing a ray from my character down so that when it hits the ground it says that im grounded.
But its not working…

I’m very new to coding, started a couple of days ago so i know this might be incredibly messy, so sorry about that!

what happens is that when the ray hits the ground it makes onGround = ture but when it leaves id doesnt uncheck it.

if anyone knows if this is possible to fix id be so thankful!

here’s the raycast:

RaycastHit hit;
        Ray checkGround = new Ray (transform.position, Vector3.down);

        Debug.DrawRay (transform.position, Vector3.down * rayLength);

        if(!onGround)
        {
            if(Physics.Raycast(checkGround, out hit, rayLength))
            {
                if(hit.collider.tag == "enviroment")
                {
                    onGround = true;
                }
            else
                {
                    onGround = cc.isGrounded;
                }
            }

And here’s the rest of the script:

using UnityEngine;
using System.Collections;

public class FPS_Controler : MonoBehaviour {

    public float movementSpeed = 10.0f;
    public float mouseSensitivity = 5.0f;
    public float jumpSpeed = 10.0f;
    public float gaY = 9.81f;
    public float maxGay = -2.0f;
    float verticalRotation = 0;
    public float Yrange = 90.0f;
    public float dieY = -150.0f;
    public int spawnNum = 0;
    public bool onGround = false;
    public float rayLength = 4.0f;

    float verticalVelocity = 0;

    // Use this for initialization
    void Start () {
        Cursor.visible = false;
        Cursor.lockState = CursorLockMode.Locked;
    }
   
    // Update is called once per frame
    void Update () {
        CharacterController cc = GetComponent<CharacterController> ();

        //Raycast
        RaycastHit hit;
        Ray checkGround = new Ray (transform.position, Vector3.down);

        Debug.DrawRay (transform.position, Vector3.down * rayLength);

        if(!onGround)
        {
            if(Physics.Raycast(checkGround, out hit, rayLength))
            {
                if(hit.collider.tag == "enviroment")
                {
                    onGround = true;
                }
            else
                {
                    onGround = cc.isGrounded;
                }
            }
        }


        // Rotation

        float rotX = Input.GetAxis ("Mouse X") * mouseSensitivity;
        transform.Rotate ( 0, rotX, 0 );


        verticalRotation -= Input.GetAxis ("Mouse Y") * mouseSensitivity;
        verticalRotation = Mathf.Clamp (verticalRotation, -Yrange, Yrange);
        Camera.main.transform.localRotation = Quaternion.Euler (verticalRotation, 0, 0);
       
        // Movement
        float forwardSpeed = Input.GetAxis ("Vertical") * movementSpeed;
        float sideSpeed = Input.GetAxis ("Horizontal") * movementSpeed;

        if (!onGround) {

            verticalVelocity += gaY * Time.deltaTime;
            if (verticalVelocity < maxGay){ verticalVelocity = maxGay;}
        }
        if (onGround) {
           
            verticalVelocity = 0;
        }
        if( onGround && Input.GetButtonDown("Jump") ) {
            verticalVelocity = jumpSpeed;
        }

        Vector3 speed = new Vector3 ( sideSpeed, verticalVelocity, forwardSpeed );

        speed = transform.rotation * speed;


        cc.Move( speed * Time.deltaTime );


        //Spawn

        float spawnY = 40.0f;
        float spawnX = 0.3f;
        Vector3 spawn = new Vector3 (spawnX, spawnY, 0);
        if(cc.transform.position.y < dieY) {
            cc.transform.position = spawn;
            spawnNum += 1;
        }
    }
}

In this part here:

if(!onGround)
{
    if(Physics.Raycast(checkGround, out hit, rayLength))
    {
        if(hit.collider.tag == "enviroment")
        {
             onGround = true;
        }
    else
        {
             onGround = cc.isGrounded;
        }
    }
}

There might be an issue because it’s checking if onGround is false before checking the conditions to set it false, which means it could break out of the loop without setting it back to false, making it unreachable to set it false again after its true… or I could be wrong but check that spot out for sure.

Edit: you should probably copy the part that sets it to cc.isGrounded out after the if that checks !onGround

Maybe like this (untested):

if(!onGround)
{
    if(Physics.Raycast(checkGround, out hit, rayLength))
    {
        if(hit.collider.tag == "enviroment")
        {
             onGround = true;
        }
    }
}
else
{
     onGround = cc.isGrounded;
}

I think you need to tweak the value of rayLength variable. If it is too big, the ray would extend long enough to hit the ground at any point in time, even when in air.

I was thinking that might be the problem too but then I didn’t see anywhere else onGround could be set false. I’m not sure though…

edit: Oh another thing that could be wrong, is that the ray might always aim for the location (0, -1, 0) - at least I’ve had some similar problem before, and you might try doing new Vector3 (transform.position.x, transform.position.y - 1, transform.position.z) instead of Vector3.down… just a thought though, good luck!

True that too!

thank you guys for responding

I tried what you said MD but that just didnt check grounded at all-

What is happening is that i fall down and the ray checks the ground for me, but it doesnt un check it when i jump off the ground again. so i fall down and then when i jump i stay in the air at the peak of the jump and every time i jump i just go up a step.

You are never setting back your “onground” bool to false. So you stay at true after the first “succesful” raycast and it never change, allowing you to jump forever.

Well, if you allow jump while !onGround, obviously you will keep jumping :slight_smile:

It doesn’t fall back down? Are you using physics? Feels like you need to attach a RigidBody to your character, and make it ‘use gravity’.

Oh yeah thats what i thought i did with the else onGround = cc.isGrounded but i guess that wasnt right…
Is there another way to tell it to go back?

as i said im very new to c# heheh i know how to talk to it but not how to write it

Try to just had an “else” after the test :

  • if(hit.collider.tag == “enviroment”)
  • {
  • onGround = true;
  • }
  • else onGround = false;

When i do that it doesnt check ground at all, i just fall and then i cant jump

Strange ! Did you change anything else ?
Try to raycast anytime and not just under condition. And to raycast anything, not just tagged objects.

Try :

Ray checkGround= new Ray(transform.position, -transform.up);
RaycastHit hit;

if (Physics.Raycast(checkGround, out hit, rayLength)) {
onGround = true;
Debug.Log (" i’m grounded ! =) “)
}
else {
onGround = false;
Debug.Log (” not grounded at all :frowning: ")
}

dear god im going insane… it says that the } after both debug.logs are unexpected

He didn’t write the ; at the end of those log statements.

Yep, my bad. Forgot the " ; " at end of the lines. How is it going ?

Try this I changed it to work right I think:

Ray checkGround= new Ray(transform.position, -transform.up);
RaycastHit hit;

if (Physics.Raycast(checkGround, out hit, rayLength))
{
onGround = true;
Debug.Log ("i'm grounded");
}
else
{
onGround = false;
Debug.Log ("not grounded");
}
1 Like

oh my god that WOOOOOORKS!! kinda!! so its checking and unchecking collision now BUT im landing on ALL the hitboxes. Above were the player is suppose to land i have a sound sphere collider which the player now… lands on… walking on sound is cool but i dont thenk that will work for this game

I tagged the object i want the ray to respond to with Enviroment and then i put if (hit.collider.tag == “Enviroment”)
in there, but that makes it not tag at all

Ray checkGround= new Ray(transform.position, -transform.up);
        RaycastHit hit;
       
        if (Physics.Raycast(checkGround, out hit, rayLength))
        {
            if (hit.collider.tag == "Enviroment") {
                Debug.Log(hit.collider.name + "Enviroment");
           

            onGround = true;
            Debug.Log ("i'm grounded");
            }
        else
        {
            onGround = false;
            Debug.Log ("not grounded");
            }
        }

Either you tag all your gameobject, or you can also delete the unused collider. Why put a collider on a sound source ? If you are not using it, remove the useless component, and get a cleaner project :wink:

Oh no i meant trigger boxes! srry, im landing on the trigger boxes.
I did remove the sound collider, that was pretty useless. But i have one more box that is set as a trigger that im landing on

To fix that, put your trigger objects the Ignore Raycast layer.

1 Like