using System.Collections; using System.Collections.Generic; using UnityEngine; namespace Nothke.Utils { public static class BoundsUtils { // static list for caching, never deallocates static List colliderCache = new List(); public static Bounds GetObjectSpaceColliderBounds(GameObject go, bool includeInactive = false) { Transform t = go.transform; var rootW2L = t.worldToLocalMatrix; go.GetComponentsInChildren(includeInactive, colliderCache); if (colliderCache.Count == 0) { Debug.LogError("Attempting to get bounds of the object but it has no colliders"); return default; } Bounds goBounds = GetBoundsInRootSpace(colliderCache[0]); for (int i = 1; i < colliderCache.Count; i++) { Bounds b = GetBoundsInRootSpace(colliderCache[i]); goBounds.Encapsulate(b); } return goBounds; Bounds GetBoundsInRootSpace(Collider col) { Bounds b = col.GetLocalBounds(); Matrix4x4 l2w = col.transform.localToWorldMatrix; Matrix4x4 local = rootW2L * l2w; return TransformBounds(local, b); } } public static Bounds GetLocalBounds(this Collider collider) { if (collider is BoxCollider) { BoxCollider box = (BoxCollider)collider; return new Bounds(box.center, box.size); } else if (collider is SphereCollider) { var center = ((SphereCollider)collider).center; var radius = ((SphereCollider)collider).radius; Vector3 size = new Vector3(radius * 2, radius * 2, radius * 2); return new Bounds(center, size); } else if (collider is CapsuleCollider) { var capsule = (CapsuleCollider)collider; var r = capsule.radius; var h = capsule.height; Vector3 size; switch (capsule.direction) { case 0: size = new Vector3(h, r * 2, r * 2); break; case 1: size = new Vector3(r * 2, h, r * 2); break; case 2: size = new Vector3(r * 2, r * 2, h); break; default: size = default; break; } return new Bounds(capsule.center, size); } else if (collider is MeshCollider) { return ((MeshCollider)collider).sharedMesh.bounds; } Debug.LogError("Attempting to get bounds of an unknown collider type"); return new Bounds(); } public static Bounds TransformBounds(in Matrix4x4 mat, in Bounds bounds) { // Find 8 corners of the bounds Vector3 p0 = bounds.min; Vector3 p1 = bounds.max; Vector3 p2 = new Vector3(p0.x, p0.y, p1.z); Vector3 p3 = new Vector3(p0.x, p1.y, p0.z); Vector3 p4 = new Vector3(p1.x, p0.y, p0.z); Vector3 p5 = new Vector3(p0.x, p1.y, p1.z); Vector3 p6 = new Vector3(p1.x, p0.y, p1.z); Vector3 p7 = new Vector3(p1.x, p1.y, p0.z); Bounds b = new Bounds(mat * p0, Vector3.zero); b.Encapsulate(mat * p1); b.Encapsulate(mat * p2); b.Encapsulate(mat * p3); b.Encapsulate(mat * p4); b.Encapsulate(mat * p5); b.Encapsulate(mat * p6); b.Encapsulate(mat * p7); return b; } public static void DrawBoundsGizmos(in Bounds bounds) { Gizmos.DrawWireCube(bounds.center, bounds.size); } } }