Unity缩放GameObject后通过Bounds生成BoxCollider尺寸过小问题求助
问题根因
Renderer.bounds返回的是世界空间下的轴对齐边界盒,已经包含了对象缩放、旋转、位移的所有变换影响BoxCollider.size是挂载对象局部坐标系下的尺寸属性,Unity运行时会自动将其乘以挂载对象的全局缩放transform.lossyScale,得到最终的世界空间碰撞盒尺寸- 原代码直接将世界空间的边界盒尺寸赋值给局部的
collider.size,相当于碰撞盒尺寸被额外乘以了一次对象缩放系数,所以对象缩放后生成的碰撞盒会远小于预期
修复方案
将计算得到的世界空间边界盒的中心和尺寸,转换为挂载对象的局部空间数值后再赋值给Collider即可,修复后代码如下:
BoxCollider collider; Bounds worldBounds = new Bounds(Vector3.zero, Vector3.zero); bool hasBounds = false; Renderer[] renderers = this.GetComponentsInChildren<Renderer>(); if (renderers.Length > 0) { foreach (Renderer renderer in renderers) { if (renderer == null) continue; if (!hasBounds) { worldBounds = renderer.bounds; hasBounds = true; } else { worldBounds.Encapsulate(renderer.bounds); } } } // 无渲染器时提前返回避免报错 if (!hasBounds) return; collider = GetComponent<BoxCollider>(); if (collider == null) { collider = gameObject.AddComponent<BoxCollider>(); } // 把世界空间的边界盒属性转换为局部空间 Vector3 localCenter = transform.InverseTransformPoint(worldBounds.center); Vector3 localSize = transform.InverseTransformVector(worldBounds.size); // 尺寸取绝对值避免负缩放导致的尺寸异常 localSize = new Vector3(Mathf.Abs(localSize.x), Mathf.Abs(localSize.y), Mathf.Abs(localSize.z)); collider.center = new Vector3(localCenter.x, localCenter.y, 0); collider.size = localSize;
额外注意事项
- 如果对象存在非90度倍数的旋转,直接Encapsulate所有渲染器的世界轴对齐边界盒,得到的结果会比实际对象的包围范围更大,若要得到更贴合的碰撞盒,需要先将顶点转换到局部空间再计算边界
- 若对象的父节点存在动态缩放,需要在缩放完成后重新执行一次上述逻辑更新碰撞盒尺寸
内容的提问来源于stack exchange,提问作者Zaki
相关产品推荐
相关产品推荐

