Skip to content

Instantly share code, notes, and snippets.

@drZool
Created October 30, 2018 13:20
Show Gist options
  • Select an option

  • Save drZool/cca7d5ad49f21e1d7edaca32714b4892 to your computer and use it in GitHub Desktop.

Select an option

Save drZool/cca7d5ad49f21e1d7edaca32714b4892 to your computer and use it in GitHub Desktop.
ColliderExtensions for checking overlapping colliders without using Unity physics.
using UnityEngine;
using System.Collections;
public static class ColliderExtensions
{
public static bool Overlaps (this BoxCollider box, SphereCollider sphere)
{
//Im sure there is a better way to do this, but it works for now.
var sphereWorldCenter = sphere.transform.TransformPoint (sphere.center);
var sphereWorldRadius = new Vector3 (sphere.transform.lossyScale.x * sphere.radius, 0, 0);
//
// Reset box to worldspace scale (1,1,1)
//
var originalBoxCenter = box.center;
var originalBoxSize = box.size;
var originalBoxScale = box.transform.localScale;
box.center = Vector3.Scale (box.center, box.transform.lossyScale);
box.size = Vector3.Scale (box.size, box.transform.lossyScale);
box.transform.SetGlobalScale (Vector3.one);
var sphereCenterInBoxSpace = box.transform.InverseTransformPoint (sphereWorldCenter) - box.center;
var s = box.transform.InverseTransformVector (sphereWorldRadius).magnitude;
float sphereRadiusInBoxSpace = s;
var extents = box.size / 2;
Vector3 distanceFromCenterOfBox = new Vector3 (Mathf.Abs (sphereCenterInBoxSpace.x), Mathf.Abs (sphereCenterInBoxSpace.y), Mathf.Abs (sphereCenterInBoxSpace.z));
bool result = false;
//float sphereRadiusInBoxSpace = Mathf.Max (Mathf.Max (s.x, s.y), s.z);
if (distanceFromCenterOfBox.x > sphereRadiusInBoxSpace + extents.x)
goto defer;
if (distanceFromCenterOfBox.z > sphereRadiusInBoxSpace + extents.z)
goto defer;
if (distanceFromCenterOfBox.y > sphereRadiusInBoxSpace + extents.y)
goto defer;
if (distanceFromCenterOfBox.x <= extents.x && distanceFromCenterOfBox.z <= extents.z && distanceFromCenterOfBox.y <= extents.y) {
result = true;
goto defer;
}
Vector3 closestPointOnBox = new Vector3 (Mathf.Clamp (sphereCenterInBoxSpace.x, -extents.x, extents.x),
Mathf.Clamp (sphereCenterInBoxSpace.y, -extents.y, extents.y),
Mathf.Clamp (sphereCenterInBoxSpace.z, -extents.z, extents.z));
var distVector = closestPointOnBox - sphereCenterInBoxSpace;
result = (distVector.sqrMagnitude < sphereRadiusInBoxSpace * sphereRadiusInBoxSpace);
defer:
//Restore box scale
box.center = originalBoxCenter;
box.size = originalBoxSize;
box.transform.localScale = originalBoxScale;
return result;
}
public static bool Overlaps (this SphereCollider sphere, BoxCollider box)
{
return box.Overlaps (sphere);
}
public static bool OverlapsDebug (this BoxCollider box, SphereCollider sphere, out Vector3 spherePos, out float sphereRadius)
{
//Im sure there is a better way to do this, but it works for now.
var sphereWorldCenter = sphere.transform.TransformPoint (sphere.center);
var sphereWorldRadius = new Vector3 (sphere.transform.lossyScale.x * sphere.radius, 0, 0);
//
// Reset box to worldspace scale (1,1,1)
//
var originalBoxCenter = box.center;
var originalBoxSize = box.size;
var originalBoxScale = box.transform.localScale;
box.center = Vector3.Scale (box.center, box.transform.lossyScale);
box.size = Vector3.Scale (box.size, box.transform.lossyScale);
box.transform.SetGlobalScale (Vector3.one);
var sphereCenterInBoxSpace = box.transform.InverseTransformPoint (sphereWorldCenter) - box.center;
var s = box.transform.InverseTransformVector (sphereWorldRadius).magnitude;
float sphereRadiusInBoxSpace = s;
var extents = box.size / 2;
Vector3 distanceFromCenterOfBox = new Vector3 (Mathf.Abs (sphereCenterInBoxSpace.x), Mathf.Abs (sphereCenterInBoxSpace.y), Mathf.Abs (sphereCenterInBoxSpace.z));
bool result = false;
//float sphereRadiusInBoxSpace = Mathf.Max (Mathf.Max (s.x, s.y), s.z);
if (distanceFromCenterOfBox.x > sphereRadiusInBoxSpace + extents.x)
goto defer;
if (distanceFromCenterOfBox.z > sphereRadiusInBoxSpace + extents.z)
goto defer;
if (distanceFromCenterOfBox.y > sphereRadiusInBoxSpace + extents.y)
goto defer;
if (distanceFromCenterOfBox.x <= extents.x && distanceFromCenterOfBox.z <= extents.z && distanceFromCenterOfBox.y <= extents.y) {
result = true;
goto defer;
}
Vector3 closestPointOnBox = new Vector3 (Mathf.Clamp (sphereCenterInBoxSpace.x, -extents.x, extents.x),
Mathf.Clamp (sphereCenterInBoxSpace.y, -extents.y, extents.y),
Mathf.Clamp (sphereCenterInBoxSpace.z, -extents.z, extents.z));
var distVector = closestPointOnBox - sphereCenterInBoxSpace;
result = (distVector.sqrMagnitude < sphereRadiusInBoxSpace * sphereRadiusInBoxSpace);
defer:
spherePos = box.transform.TransformPoint (sphereCenterInBoxSpace);
var s2 = box.transform.TransformVector (new Vector3 (sphereRadiusInBoxSpace, 0, 0));
sphereRadius = s2.magnitude;
//Restore box transforms
box.center = originalBoxCenter;
box.size = originalBoxSize;
box.transform.localScale = originalBoxScale;
return result;
}
public static void SetGlobalScale (this Transform transform, Vector3 globalScale)
{
transform.localScale = Vector3.one;
var lossyScale = transform.lossyScale;
transform.localScale = new Vector3 (globalScale.x / lossyScale.x, globalScale.y / lossyScale.y, globalScale.z / lossyScale.z);
}
public static bool OverlapsDebug (this SphereCollider sphere, BoxCollider box, out Vector3 spherePos, out float sphereRadius)
{
return box.OverlapsDebug (sphere, out spherePos, out sphereRadius);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment