Unity - How to make Raycast hit on backface of mesh from inside of it?

hi, I have a Raycast that is originating from inside of a cube, and shooting downwards.
I would like for the Raycast to be able to detect the bottom face of the cube that it’s inside of; instead, it is simply traveling through the bottom of the cube.
I tried to screenshot and illustrate the problem…

I used Physics.queriesHitBackfaces in my script and also turned on that option in Project Settings -> Physics but raycast is still traveling straight through bottom of cube.

From the Unity documentation:

Afaik there is no setting to circumvent this - even queriesHitBackfaces is confusing and doesn’t seem to work, but there are ways that may work if you have enough data.

One method is to pick a point below the collider that you know is outside of it and shooting the ray towards the origin, i.e. reversing the ray. the hit position will be the same point as it would have been had the ray collided with the inside of the collider (since colliders don’t have a ‘wall thickness’).


Edit

If you don’t know a point outside the collider (perhaps you don’t know how big the collider is) you can perform some sort of ray march, although you’d need to tweak it to get acceptable performance.

What you’d do is pick a ‘step size’ - say 10 units - and then shoot the ray from there to the origin. The length of the ray should be the distance from the ray’s origin to the point inside the collider (this should be the case for the previous method, too). If you hit nothing, move a little farther away and try again. Continue until you’ve hit something. It would be something like this

public bool Raymarch(Vector3 origin, Vector3 direction, float stepSize, out RaycastHit hit, int maxSteps = 5)
{
    // move ray in the opposite direction
    var rayDirection = -direction;
    // we start the iteration at 1 to avoid the useless check where the ray starts at the origin.
    // we could have left this 0 and just added 1 when we calculated the ray origin
    for (var step = 1; step <= maxSteps; step++)
    {
        // move the ray to a point that is stepSize * step away from the origin (in the direction we want to check)
        var rayOrigin = origin + direction * step * stepSize;
        // create a ray from this position, toward the origin
        var ray = new Ray(rayOrigin, rayDirection);
        // check if we hit something. we only check the distance to stepSize since we already know that there's no hits beyond that.
        // we could calculate the distance from here to the origin, but it's not necessary
        if (Physics.Raycast(ray, out hit, stepSize))
            return true; // we have a hit, so return true.
    }
    // if we got to here, we had no hit in the parameters specified. We may want to increase the stepSize or maxSteps. This requires tweaking
    hit = default;
    return false;
}

// Usage:
if (Raymarch(transform.position, Vector3.down, 10f, out var hit))
    Debug.Log($"We hit the collider at {hit.point}");

// Small print: I didn't test this.
1 Like

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.

Privacy & Terms