Search code examples
c#unity-game-engineraycasting

Use of unassigned local variable (CS0165) Raycasting in unity


I have this piece of script that I made and I get this error and I don't understand why

RaycastHit HitFL, HitFR, HitBL, HitBR;

grounded = CastRayFrontLeft(out HitFL) || CastRayFrontRight(out HitFR) ||
           CastRayBackLeft(out HitBL) || CastRayBackRight(out HitBR);
VehiculeNormal = ((  HitFL.normal
                   + HitFR.normal
                   + HitBL.normal
                   + HitBR.normal) / 4).normalized;

enter image description here

as you can witness, .net thinks the HitFR BL and BR are not assigned but they are just above.

I came to think that the execution of the boolean expression is stopped after CastRayFrontLeft(out HitFL) because it's the only one that does not throw an error but I don't understand why it should work that way.

any answer to this problem I found could not help since, in their's, they did not assign a value which I do in mine.

if some boy can help me I would highly appreciate it.

EDIT:

following is the code related to the custom functions

private bool CastRayFrontRight(out RaycastHit hit)
{
    return Physics.Raycast(RayCasterFrontRight.position, -transform.up, out hit, .5f);
}

public bool CastRayFrontLeft(out RaycastHit hit)
{
    return Physics.Raycast(RayCasterFrontLeft.position, -transform.up, out hit, .5f);
}

private bool CastRayBackRight(out RaycastHit hit)
{
    return Physics.Raycast(RayCasterBackRight.position, -transform.up, out hit, .5f);
}

public bool CastRayBackLeft(out RaycastHit hit)
{
    return Physics.Raycast(RayCasterBackLeft.position, -transform.up, out hit, .5f);
}

Solution

  • The problem is the short-circuit evaluation of C#. When terms are combined with || (OR), the second term is only evaluated, if the first one returns false, because otherwise, the outcome is known without evaluating it.

    Therefore, change the code to:

    var castFL = CastRayFrontLeft(out HitFL);
    var castFR = CastRayFrontRight(out HitFR);
    var castBL = CastRayBackLeft(out HitBL);
    var castBR = CastRayBackRight(out HitBR);
    grounded = castFL || castFR || castBL || castBR;
    VehiculeNormal = ((  HitFL.normal
                       + HitFR.normal
                       + HitBL.normal
                       + HitBR.normal) / 4).normalized;
    

    As an alternative, you can also combine the terms with the bitwise OR operator |:

    grounded = CastRayFrontLeft(out HitFL) | CastRayFrontRight(out HitFR) | 
               CastRayBackLeft(out HitBL) | CastRayBackRight(out HitBR);
    VehiculeNormal = ((  HitFL.normal
                       + HitFR.normal
                       + HitBL.normal
                       + HitBR.normal) / 4).normalized;
    

    However, as @derHugo pointed out, there is a fundamental issue with your geometrical logic. If a ray doesn't hit, the resulting normal will be (0, 0, 0). Therefore you should only consider rays that did actually hit.