Angled Physics.Raycast not returning true (C# / C sharp)

Intro

In game world theres a capsule player marked with layer !playerBody to be ignorred by ray.
Debug.DrawRay(); shows the rays correctly.

Rays are shot from a middle point down and out; forming a cone shape w/ a slight lip underneath player.


Goal

A dynamic amount of rays will test for ‘isGrounded’ on ‘playerBody’:

isGrounded == true : On the ground

isGrounded == false : Air borne


Pseudo code

(Player on slope)

  1. Ray1:False → Next, Ray2:False → Next, Ray3:True → BoolTrue (Start over)

  2. Ray1-16:False → BoolFalse (Start over)


Problem

Raycast allways returns false.


NOTE

Camera and playerCapsule(rigidBody, constrainedRotation) movement is excluded from example script.

_
alt text


public class X: MonoBehaviour
{
    public bool isGrounded = false;

    public int rayAmount = 20;                  //Amount of rays cast

    public float rayOffset = -3f;
    public float rayRadius = 0.35f;

    public LayerMask groundingRayLayerMasking;  //Layers to ignore: !playerBody

    void FixedUpdate ()
    {
        Vector3 playerPos = transform.position;

        int j = 0;  //Do not delete!

        for (int i = 1; i < rayAmount; i++)
        {
            RaycastHit tempHit = new RaycastHit();

            if (j > (rayAmount - 1)) // (rayAmount(16)-1)::(since 0 incl. and '0' is required for calc. of 'angle')
            {
                j = 0;
            }

            float angle = j * Mathf.PI * 2 / rayAmount;
            Vector3 pos = new Vector3(Mathf.Cos(angle), rayOffset, Mathf.Sin(angle)) * rayRadius;

            //float temp_rayDistance = Vector3.Distance(playerPos, pos);  //TEMP

            Debug.DrawRay(playerPos, pos, Color.blue, Time.deltaTime, false);

            //Debug.Log(temp_rayDistance);    //TMEP

            if (Physics.Raycast(playerPos, (pos + playerPos), out tempHit, 5.2f, groundingRayLayerMasking))
            {
                //Debug.Log("groundRay hit");
                isGrounded = true;

                i = 0;  //Restart squence from 0
                j = 0;  //Restart squence from 0
                //break;
            }
            else
            {
                //Debug.Log("No groundRay hit");
                isGrounded = false;

                if (i > (rayAmount - 1))//Restart sequence reaching end!
                {
                    i = 0;
                }
            }
            j++;
        }
    }
}

The documentation on the Physics.Raycast is a bit poorly written, but in reality the layermask you provide is for the layers you want to collide with, not the ones you want to ignore. I know the documentation says “A Layer mask that is used to selectively ignore Colliders when casting a ray”, but that’s because in the example it’s used as such, but if you notice the actual example code and comments:

// Bit shift the index of the layer (8) to get a bit mask
int layerMask = 1 << 8;

// This would cast rays only against colliders in layer 8.
// But instead we want to collide against everything except layer 8. The ~ operator does this, it inverts a bitmask.
layerMask = ~layerMask;

They invert the bitmask, so in reality the mask has everything except for the selected layer, thus resulting in it being ignored.

In other words, if you add to your code:

private void Start()
{
    groundingRayLayerMasking = ~groundingRayLayerMasking;
}

I would expect the collision to behave normally. Please let me and others know if this works.

–EDIT–

I see that you’re also setting isGrounded to false whenever a single raycast fails, and that causes only the last raycast to have any effect. Do remove that part as well. Instead, only set IsGrounded to false before the loop, and only set it to true inside the loop, whenever a hit occurs (and then break the loop).
PS: Why did you comment out the break; part of your loop?
PPS: Why would you want your loop to reset (by making i=0)? Won’t this cause an infinite loop in some situations? That could also very well be a reason the loop never exits with a isGrounded == true state.