11// Adjust Box Collider to fit child meshes inside
22// Usage: You have empty parent transform, with child meshes inside, add box collider to parent then use this
3- // NOTE: Doesnt work if root transform is rotated
43
54using UnityEngine ;
65using UnityEditor ;
@@ -10,44 +9,52 @@ namespace UnityLibrary
109 public class BoxColliderFitChildren : MonoBehaviour
1110 {
1211 [ MenuItem ( "CONTEXT/BoxCollider/Fit to Children" ) ]
13- static void FixSize ( MenuCommand command )
12+ static void FitColliderToChildren ( MenuCommand command )
1413 {
1514 BoxCollider col = ( BoxCollider ) command . context ;
1615
17- // Record undo for undo functionality
16+ // record undo
1817 Undo . RecordObject ( col . transform , "Fit Box Collider To Children" ) ;
1918
20- // Get transformed bounds relative to the collider object
21- Bounds localBounds = GetLocalBounds ( col . transform ) ;
19+ // first reset transform rotation
20+ var origRot = col . transform . rotation ;
21+ col . transform . rotation = Quaternion . identity ;
2222
23- // Set collider local center and size
24- col . center = localBounds . center ;
25- col . size = localBounds . size ;
26- }
23+ // get child mesh bounds
24+ var b = GetRecursiveMeshBounds ( col . gameObject ) ;
2725
28- public static Bounds GetLocalBounds ( Transform parent )
29- {
30- var renderers = parent . GetComponentsInChildren < Renderer > ( ) ;
31- if ( renderers . Length == 0 )
32- return new Bounds ( Vector3 . zero , Vector3 . zero ) ; // No renderers
26+ // set collider local center and size
27+ col . center = col . transform . root . InverseTransformVector ( b . center ) - col . transform . position ;
3328
34- // Initialize bounds in local space
35- Bounds bounds = new Bounds ( parent . InverseTransformPoint ( renderers [ 0 ] . bounds . center ) ,
36- parent . InverseTransformVector ( renderers [ 0 ] . bounds . size ) ) ;
29+ // keep size positive
30+ var size = b . size ;
31+ size . x = Mathf . Abs ( size . x ) ;
32+ size . y = Mathf . Abs ( size . y ) ;
33+ size . z = Mathf . Abs ( size . z ) ;
3734
38- // Encapsulate all child renderers
39- for ( int i = 1 ; i < renderers . Length ; i ++ )
40- {
41- var worldBounds = renderers [ i ] . bounds ;
35+ col . size = b . size ;
4236
43- // Convert world bounds to local space
44- Vector3 localCenter = parent . InverseTransformPoint ( worldBounds . center ) ;
45- Vector3 localSize = parent . InverseTransformVector ( worldBounds . size ) ;
37+ // restore rotation
38+ col . transform . rotation = origRot ;
39+ }
4640
47- bounds . Encapsulate ( new Bounds ( localCenter , localSize ) ) ;
41+ public static Bounds GetRecursiveMeshBounds ( GameObject go )
42+ {
43+ var r = go . GetComponentsInChildren < Renderer > ( ) ;
44+ if ( r . Length > 0 )
45+ {
46+ var b = r [ 0 ] . bounds ;
47+ for ( int i = 1 ; i < r . Length ; i ++ )
48+ {
49+ b . Encapsulate ( r [ i ] . bounds ) ;
50+ }
51+ return b ;
52+ }
53+ else // TODO no renderers?
54+ {
55+ //return new Bounds(Vector3.one, Vector3.one);
56+ return new Bounds ( ) ;
4857 }
49-
50- return bounds ;
5158 }
5259 }
5360}
0 commit comments