Skip to content

Commit 3039e53

Browse files
authored
Update BoxColliderFitChildren.cs
fix rotated objects, fix negative scale
1 parent ace9f47 commit 3039e53

File tree

1 file changed

+34
-27
lines changed

1 file changed

+34
-27
lines changed
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
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

54
using UnityEngine;
65
using 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

Comments
 (0)