Rays keep detecting a collider even when not hitting it?

EDIT: The script seems to work correctly if I don’t use a List and loop through the objects. But I don’t understand why I seemingly can’t use a List.

(method below is constantly running in Update)

void checkCollisions()
    {

        leftCornerLeft = Physics2D.Raycast(topLeftOrigin, Vector3.left, rayLength);

        if(leftCornerLeft.collider != null)
        {
            //works as intended - if hitting collider this is sent, but if not this isn't sent
            Debug.Log("hit!!!");
        }
    }

Original: I’m experimenting with keeping my player from being able to go through other gameobjects in a scene. Currently I’m simply using small raycasthit2Ds, sent out from positions close to the player’s collider - when one hits a collider, a Debug.Log is sent. (Eventually it’ll stop movement in the direction of the ray.)

However I’ve run into a problem - even when the ray isn’t hitting an object, Log messages are still being recorded. I think this has something to do with Update, perhaps the checkCollisions method is constantly creating new rays, but at the same time, something has to be constantly updated because otherwise the rays don’t move with the collider (ie, creating them in Start won’t update their positions).

Basically the Debug.Log messages don’t start until a collider is detected (like I want), but even when the when the rays stop hitting the collider, the messages keep getting sent (which I don’t want). I think the problem has to do with Update. The problem shouldn’t be the player’s own collider. Thanks for any help in advance.

    RaycastHit2D leftCornerUp, leftCornerLeft;
    List<RaycastHit2D> rays = new List<RaycastHit2D>();

    float rayLength = 0.05f;
    public CharacterMoveClamp charMoveClampScript;
    Collider2D charCollider;


    public void Start()
    {
        charCollider = GetComponent<Collider2D>();
    }

    // Update is called once per frame
    void Update()
    {
        checkCollisions();
    }

    void checkCollisions()
    {
        //position the "up" raycast
        Vector3 topLeftOrigin = new Vector3(charCollider.bounds.min.x, charCollider.bounds.max.y);
      
        //use the CreateRaycasts method to create and return the raycast values
        leftCornerLeft = CreateRaycasts(topLeftOrigin, Vector3.up);
        leftCornerUp = CreateRaycasts(topLeftOrigin, Vector3.left);

        //add the arrays to the list
        rays.Add(leftCornerLeft);
        rays.Add(leftCornerUp);

        Debug.DrawLine(topLeftOrigin, new Vector3(topLeftOrigin.x, topLeftOrigin.y + rayLength), Color.cyan);
        Debug.DrawLine(topLeftOrigin, new Vector3(topLeftOrigin.x - rayLength, topLeftOrigin.y), Color.cyan);

        //loop through rays and see if any are hitting a collider
        for (var i = 0; i < rays.Count; i++)
        {
            if (rays[i].collider != null)
            {
                Debug.Log("hit");
            }
        }
    }

    RaycastHit2D CreateRaycasts(Vector3 rayCoordinates, Vector3 rayDirection)
    {
        return Physics2D.Raycast(rayCoordinates, rayDirection, rayLength);
    }
}

The only thing is you are constantly adding new raycasts every frame to the List. It would be better to create an array right in the function if you are going to want an array of two values, or else clear the list each frame.

1 Like

Yep, you’re adding them to the list, and if you had tested long enough it would have gotten ridiculous.
You could keep the array (or list) just 2 long, and assign directly to the index:

rays[0] = upperLeft;
rays[1] = upperTop;

Overwriting them, as well as keeping the count at 2. :slight_smile:
If you do do that with a list, instead of an array, make sure to add 2 to the list (with ‘.Add’) before your update loop.

1 Like

I wanted to experiment with Lists since I’ve never really used those before. I’ll probably ultimately end up using an array though, since the number of rays used won’t change. But in any case I think I solved my current problem thanks to these responses.

Yeah I definitely noticed a slowdown after a few seconds. :stuck_out_tongue:

Like I said above I’ll probably ultimately use an Array. I was originally confused because the Scripting API said “The Array class is only available in Javascript.” But I didn’t read further and missed the part about “builtin arrays” - “There are two types of arrays in Unity, builtin arrays and normal Javascript Arrays. Builtin arrays (native .NET arrays), are extremely fast and efficient but they can not be resized.”

I still have a question about this:

By update loop do you mean 1) Update() method, or 2) the “for” loop I’m using to check if the rays hit a collider? I’m currently doing the 2 and it is working thus far.

Related, I thought I could add the rays to the List in the Start() method, so they are only added once to the List (thus I wouldn’t need to remove them from the list at the end of the method)

RaycastHit2D leftCornerUp, leftCornerLeft;
public void Start()
    {
        rays.Add(leftCornerLeft);
        rays.Add(leftCornerUp);
    }

And just update the rays in the Update() method

void Update ()
    {
        checkCollisions();
    }

    void checkCollisions()
    {
...
leftCornerLeft = CreateRaycasts(topLeftOrigin, Vector3.up);
        leftCornerUp = CreateRaycasts(topLeftOrigin, Vector3.left);
...
}

for (var i = 0; i<rays.Count; i++)
        {
            if (rays[i].collider != null)
            {
                Debug.Log("hit");
            }
        }

But this doesn’t seem to work/update correctly, for some reason; I assume it has something to do with ray info not updating since it was added in Start().

It doesn’t matter if you use a list or array, but arrays are faster, so if the size is fixed, arrays are a better choice. Like methos5k wrote, you need to overwrite in your check collisions, either with an array or a list:
rays[0] = leftCornerLeft;//done in checkCollisions

I would suggest getting it to work with both an array and a list. Like methos said, you need to add two rays to the list in the start method so they are initialized. Then you can overwrite in check collisions.
The array is initialized when you give it a size.

1 Like

And this is because the ray’s information is otherwise not added/updated to the array? I can’t do “rays[0] = leftCornerLeft;” in Start() and expect the ray’s new position and other info to automatically be pushed to the array?

EDIT: Or maybe I’m thinking about it wrong. (I’m tired. :P) Maybe since

leftTopLeft = CreateRaycasts(topLeftOrigin, Vector3.up);
        upTopLeft = CreateRaycasts(topLeftOrigin, Vector3.left);

is in Update(), I’m constantly creating new rays as the character moves, thus the new rays have to be added to the List or Array.

No, it’s just a copy of that instance you created during that one frame. You have to create the ray each time and overwrite the last one, or use it as is. It’s like any other variable, but in an array.

1 Like

Yeah I think that’s what I figured out as you were typing. :slight_smile: