1
1
// Adjust Box Collider to fit child meshes inside
2
2
// 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
4
3
5
4
using UnityEngine ;
6
5
using UnityEditor ;
@@ -10,44 +9,52 @@ namespace UnityLibrary
10
9
public class BoxColliderFitChildren : MonoBehaviour
11
10
{
12
11
[ MenuItem ( "CONTEXT/BoxCollider/Fit to Children" ) ]
13
- static void FixSize ( MenuCommand command )
12
+ static void FitColliderToChildren ( MenuCommand command )
14
13
{
15
14
BoxCollider col = ( BoxCollider ) command . context ;
16
15
17
- // Record undo for undo functionality
16
+ // record undo
18
17
Undo . RecordObject ( col . transform , "Fit Box Collider To Children" ) ;
19
18
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 ;
22
22
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 ) ;
27
25
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 ;
33
28
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 ) ;
37
34
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 ;
42
36
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
+ }
46
40
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 ( ) ;
48
57
}
49
-
50
- return bounds ;
51
58
}
52
59
}
53
60
}
0 commit comments