1

Problem Description: I am implementing collision detection between an OBB and an AABB using the Separating Axis Theorem (SAT) in Unity. The algorithm works perfectly in most cases, but I have noticed an issue:

When the AABB is close to a world axis (e.g., X ≈ 0, Y ≈ 0, or Z ≈ 0), collisions are not detected properly. Objects that should be colliding pass through each other.

=> Expected behavior: The SAT should detect collisions reliably regardless of world position. => Actual behavior: Collisions fail when the AABB is near Unity's world axes.

Here is my code:

public bool IntersectAABB(AABBObstacle aabb)
    {
        Vector3[] aabbCorners = aabb.GetCorners();

        Vector3[] aabbAxes = new Vector3[] { Vector3.right, Vector3.up, Vector3.forward };

        Vector3[] obbAxes = new Vector3[]
        {
            rotation * Vector3.right,
            rotation * Vector3.up,
            rotation * Vector3.forward
        };

        List<Vector3> axesToTest = new();

        axesToTest.AddRange(aabbAxes);

        axesToTest.AddRange(obbAxes);

        for (int i = 0; i < 3; i++)
        {
            for (int j = 0; j < 3; j++)
            {
                Vector3 axis = Vector3.Cross(obbAxes[i], aabbAxes[j]);
                if (axis != Vector3.zero)
                    axesToTest.Add(axis.normalized);
            }
        }

        foreach (Vector3 axis in axesToTest)
        {
            if (IsSeparatingAxis(axis, corners, aabbCorners))
            {
                return false;
            }
        }

        return true;
    }

    private bool IsSeparatingAxis(Vector3 axis, Vector3[] obbCorners, Vector3[] aabbCorners)
    {
        if (axis == Vector3.zero)
            return false;

        float obbMin = float.MaxValue,
            obbMax = float.MinValue;
        float aabbMin = float.MaxValue,
            aabbMax = float.MinValue;

        foreach (Vector3 corner in obbCorners)
        {
            float projection = Vector3.Dot(corner, axis);
            obbMin = Mathf.Min(obbMin, projection);
            obbMax = Mathf.Max(obbMax, projection);
        }

        foreach (Vector3 corner in aabbCorners)
        {
            float projection = Vector3.Dot(corner, axis);
            aabbMin = Mathf.Min(aabbMin, projection);
            aabbMax = Mathf.Max(aabbMax, projection);
        }

        return obbMax < aabbMin || aabbMax < obbMin;
    }

I've logged all projection values, min/max intervals, and separating axis tests, and everything seems coherent. The projections of the OBB and AABB corners onto each axis appear correct, but some values are very close. I added a small tolerance (1e-4f) to the interval checks, which reduced false negatives but didn’t fully solve the issue.

I also discarded near-zero cross-product axes (sqrMagnitude < 1e-6f), but it had no effect.

Thank you for your help!

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.