|
| 1 | +using System; |
1 | 2 | using System.Collections; |
2 | 3 | using System.Collections.Generic; |
3 | 4 | using System.Linq; |
@@ -98,30 +99,61 @@ public static void Destroy(this Object obj) |
98 | 99 | Object.Destroy(obj); |
99 | 100 | } |
100 | 101 | } |
101 | | - |
102 | | - public static Bounds GetLocalBoundsForChildrenMeshes(GameObject go) |
| 102 | + |
| 103 | + /// <summary> |
| 104 | + /// Adjusts the GameObject’s BoxCollider to bounding box for all child meshes. |
| 105 | + /// </summary> |
| 106 | + /// <param name="gameObject">Target GameObject.</param> |
| 107 | + /// <param name="boxCollider">The BoxCollider if found and updated; null otherwise.</param> |
| 108 | + /// <returns>True if the collider was found and updated; false on error.</returns> |
| 109 | + public static bool TryBoundBoxColliderSize(GameObject gameObject, out BoxCollider boxCollider) |
103 | 110 | { |
104 | | - var referenceTransform = go.transform; |
105 | | - var b = new Bounds(Vector3.zero, Vector3.zero); |
106 | | - RecurseEncapsulate(referenceTransform, ref b); |
107 | | - return b; |
108 | | - |
109 | | - void RecurseEncapsulate(Transform child, ref Bounds bounds) |
| 111 | + try |
110 | 112 | { |
111 | | - var mesh = child.GetComponent<MeshFilter>(); |
112 | | - if (mesh) |
113 | | - { |
114 | | - var lsBounds = mesh.sharedMesh.bounds; |
115 | | - var wsMin = child.TransformPoint(lsBounds.center - lsBounds.extents); |
116 | | - var wsMax = child.TransformPoint(lsBounds.center + lsBounds.extents); |
117 | | - bounds.Encapsulate(referenceTransform.InverseTransformPoint(wsMin)); |
118 | | - bounds.Encapsulate(referenceTransform.InverseTransformPoint(wsMax)); |
119 | | - } |
120 | | - foreach (Transform grandChild in child.transform) |
| 113 | + if (gameObject == null) throw new NullReferenceException("GameObject is null"); |
| 114 | + boxCollider = gameObject.GetComponent<BoxCollider>(); |
| 115 | + if (boxCollider == null) |
121 | 116 | { |
122 | | - RecurseEncapsulate(grandChild, ref bounds); |
| 117 | + throw new NullReferenceException("BoxCollider is null"); |
123 | 118 | } |
| 119 | +#if UNITY_EDITOR |
| 120 | + UnityEditor.Undo.RecordObject(boxCollider, "Set Box Collider Bound Size"); |
| 121 | +#endif |
| 122 | + var bounds = GetLocalBoundsForChildrenMeshes(gameObject); |
| 123 | + boxCollider.center = bounds.center; |
| 124 | + boxCollider.size = bounds.size; |
| 125 | + |
| 126 | +#if UNITY_EDITOR |
| 127 | + |
| 128 | + UnityEditor.EditorUtility.SetDirty(gameObject); |
| 129 | +#endif |
| 130 | + return true; |
| 131 | + } |
| 132 | + catch (Exception exception) |
| 133 | + { |
| 134 | + Debug.LogError($"TryBoundBoxColliderSize: {exception}", gameObject); |
| 135 | + boxCollider = null; |
| 136 | + return false; |
| 137 | + } |
| 138 | + } |
| 139 | + |
| 140 | + /// <summary> |
| 141 | + /// Computes the local-space axis-aligned Bounds that encapsulate all MeshFilter meshes in the given GameObject’s hierarchy. |
| 142 | + /// </summary> |
| 143 | + /// <param name="gameObject">Target GameObject.</param> |
| 144 | + /// <returns>Bounds in the GameObject’s local space covering all child meshes.</returns> |
| 145 | + public static Bounds GetLocalBoundsForChildrenMeshes(GameObject gameObject) |
| 146 | + { |
| 147 | + var transform = gameObject.transform; |
| 148 | + var localBounds = new Bounds(Vector3.zero, Vector3.zero); |
| 149 | + var filters = gameObject.GetComponentsInChildren<MeshFilter>(); |
| 150 | + foreach (var meshFilter in filters) |
| 151 | + { |
| 152 | + var matrix = transform.localToWorldMatrix.inverse * meshFilter.transform.localToWorldMatrix; |
| 153 | + var axisAlignedBounds = GeometryUtility.CalculateBounds(meshFilter.sharedMesh.vertices, matrix); |
| 154 | + localBounds.Encapsulate(axisAlignedBounds); |
124 | 155 | } |
| 156 | + return localBounds; |
125 | 157 | } |
126 | 158 | } |
127 | 159 | } |
0 commit comments