What's the best/easiest way to do something like Bounds.Intersects but accounting for rotation?

I need to compare two cuboid volumes to see if they will overlap, but I need to take rotation into consideration. I also need to do this immediately, so I can’t just use OnTriggerEnter or OnCollisionEnter, which would require waiting for a physics update. I was using Bounds.Intersect for this, and it worked great, but it can’t handle rotation.

Is there a way to do this without having to do a lot of math by hand? And if not, can anyone recommend a particular approach?

Thank you.

This is easy to use if you use mesh.bounds (on a cube), because that’s in local space.

Please let me know if you profile, and obtain a performance comparison with and without the “ContainsAny” line.

namespace UnityEngine
{
	using System;
	using System.Collections.Generic;
	using System.Linq;
	
	public static class BoundsExtensions
	{
		/// <param name="transform1">Transform of the Game Object associated with bounds1</param>
		/// <param name="transform2">Transform of the Game Object associated with bounds12</param>
		public static bool Intersects(this Bounds bounds1, Bounds bounds2, Transform transform1, Transform transform2)
		{
			Vector3[] bounds1Points = transform2.InverseTransformPoints(bounds1.EnumeratePoints(), transform1).ToArray();
			Vector3[] bounds2Points = transform1.InverseTransformPoints(bounds2.EnumeratePoints(), transform2).ToArray();

			// This is redundant, because this will return true in a subset of cases 
			// with edge intersections, but Unity's methods are not in C# and might be faster.
			// Requires profiling.
			if ( bounds1.ContainsAny(bounds2Points) || bounds2.ContainsAny(bounds1Points) )
			   return true;

			Func<Vector3, Vector3, Bounds, bool> edgeIntersectsBounds = (point1, point2, bounds) =>
			{
				Ray ray = new Ray(point1, point2 - point1);
				if ( !bounds.IntersectRay(ray) )
					return false;
				
				ray.origin = point2;
				ray.direction = -ray.direction;
				return bounds.IntersectRay(ray);
			};

			Func<Vector3[], Bounds, bool> pointsContainIntersectingEdge = (points, bounds) =>
			{
				for (int i = 0; i < points.Length - 1; i++)
					if (  points.Skip(i + 1).Any( p => edgeIntersectsBounds(points*, p, bounds) )  )*
  •  				return true;*
    
  •  		return false;*
    
  •  	};*
    
  •  	return pointsContainIntersectingEdge(bounds2Points, bounds1) || pointsContainIntersectingEdge(bounds1Points, bounds2);*
    
  •  }*
    
  •  public static bool ContainsAny(this Bounds bounds, IEnumerable<Vector3> points)*
    
  •  {*
    
  •  	return points.Any( p => bounds.Contains(p) );*
    
  •  }*
    
  •  public static IEnumerable<Vector3> EnumeratePoints(this Bounds bounds)*
    
  •  {*
    
  •  	yield return bounds.min;*
    
  •  	yield return bounds.max;*
    
  •  	for (int axis = 0; axis < 3; axis++)*
    
  •  	{*
    
  •  		Vector3 point = bounds.min;*
    
  •  		point[axis] += bounds.size[axis];*
    
  •  		yield return point;*
    
  •  		point = bounds.max;*
    
  •  		point[axis] -= bounds.size[axis];*
    
  •  		yield return point;*
    
  •  	}*
    
  •  }*
    
  • }*
    }
    namespace UnityEngine
    *{ *

  • using System.Collections.Generic;*

  • using System.Linq;*

  • public static class TransformExtensions*

  • {*

  •  /// <summary>*
    
  •  /// from local to world space*
    
  •  /// </summary>*
    
  •  public static IEnumerable<Vector3> TransformPoints(this Transform transform, IEnumerable<Vector3> points)*
    
  •  {*
    
  •  	return points.Select( p => transform.TransformPoint(p) );*
    
  •  }*
    
  •  /// <summary>*
    
  •  /// from world to local space*
    
  •  /// </summary>*
    
  •  public static IEnumerable<Vector3> InverseTransformPoints(this Transform transform, IEnumerable<Vector3> points)*
    
  •  {*
    
  •  	return points.Select( p => transform.InverseTransformPoint(p) );*
    
  •  }*
    
  •  /// <summary>*
    
  •  /// Puts points from another Transform's local space into this one's.*
    
  •  /// </summary>*
    
  •  public static IEnumerable<Vector3> InverseTransformPoints(this Transform transform, IEnumerable<Vector3> points, Transform otherTransform)*
    
  •  {*
    
  •  	return transform.InverseTransformPoints( otherTransform.TransformPoints(points) );*
    
  •  }*
    
  • }*
    }