1
- // Adjust Box Collider to fit child meshes inside
2
- // Usage: You have empty parent transform, with child meshes inside, add box collider to parent then use this
3
-
4
1
using UnityEngine ;
5
2
using UnityEditor ;
6
3
@@ -13,48 +10,62 @@ static void FitColliderToChildren(MenuCommand command)
13
10
{
14
11
BoxCollider col = ( BoxCollider ) command . context ;
15
12
16
- // record undo
13
+ // Record undo
17
14
Undo . RecordObject ( col . transform , "Fit Box Collider To Children" ) ;
18
15
19
- // first reset transform rotation
20
- var origRot = col . transform . rotation ;
21
- col . transform . rotation = Quaternion . identity ;
16
+ // Get world-space bounds of all child meshes
17
+ var worldBounds = GetRecursiveMeshBounds ( col . gameObject ) ;
22
18
23
- // get child mesh bounds
24
- var b = GetRecursiveMeshBounds ( col . gameObject ) ;
19
+ if ( worldBounds . size == Vector3 . zero )
20
+ {
21
+ Debug . LogWarning ( "No valid meshes found to fit the BoxCollider." ) ;
22
+ return ;
23
+ }
25
24
26
- // set collider local center and size
27
- col . center = col . transform . root . InverseTransformVector ( b . center ) - col . transform . position ;
25
+ // Convert world-space center to local space
26
+ Vector3 localCenter = col . transform . InverseTransformPoint ( worldBounds . center ) ;
28
27
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 ) ;
28
+ // Convert world-space size to local space
29
+ Vector3 localSize = col . transform . InverseTransformVector ( worldBounds . size ) ;
34
30
35
- col . size = b . size ;
31
+ // Ensure size is positive
32
+ localSize = new Vector3 ( Mathf . Abs ( localSize . x ) , Mathf . Abs ( localSize . y ) , Mathf . Abs ( localSize . z ) ) ;
33
+
34
+ // Fix potential center flipping
35
+ if ( Vector3 . Dot ( col . transform . right , Vector3 . right ) < 0 )
36
+ {
37
+ localCenter . x = - localCenter . x ;
38
+ }
39
+ if ( Vector3 . Dot ( col . transform . up , Vector3 . up ) < 0 )
40
+ {
41
+ localCenter . y = - localCenter . y ;
42
+ }
43
+ if ( Vector3 . Dot ( col . transform . forward , Vector3 . forward ) < 0 )
44
+ {
45
+ localCenter . z = - localCenter . z ;
46
+ }
36
47
37
- // restore rotation
38
- col . transform . rotation = origRot ;
48
+ // Apply to collider
49
+ col . center = localCenter ;
50
+ col . size = localSize ;
39
51
}
40
52
41
53
public static Bounds GetRecursiveMeshBounds ( GameObject go )
42
54
{
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);
55
+ Renderer [ ] renderers = go . GetComponentsInChildren < Renderer > ( ) ;
56
+
57
+ if ( renderers . Length == 0 )
56
58
return new Bounds ( ) ;
59
+
60
+ // Start with the first renderer’s bounds in world space
61
+ Bounds worldBounds = renderers [ 0 ] . bounds ;
62
+
63
+ for ( int i = 1 ; i < renderers . Length ; i ++ )
64
+ {
65
+ worldBounds . Encapsulate ( renderers [ i ] . bounds ) ;
57
66
}
67
+
68
+ return worldBounds ;
58
69
}
59
70
}
60
71
}
0 commit comments