You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 05:09:01