Reputation: 11
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!
Upvotes: 1
Views: 16