如何程序化获取带旋转GameObject的四个外围点?
解决方案:获取随GameObject旋转同步的外围点
你的问题核心是原来的方法计算的是世界空间轴对齐的包围盒,当父物体旋转时,这个包围盒不会跟随物体的局部坐标系旋转,导致外围点位置不符合预期。可以通过先计算父物体局部空间的包围盒,再将其转换到世界空间的方式解决。
步骤1:计算父物体局部空间的总包围盒
这个方法会遍历所有子物体的Renderer,把它们的包围盒转换到父物体的局部空间后合并,得到能反映物体自身形状的局部包围盒:
private Bounds GetLocalBounds() { var renderers = GetComponentsInChildren<Renderer>(); if (renderers.Length == 0) return new Bounds(); // 初始化第一个子物体的局部包围盒(转换到父物体局部空间) Renderer firstRenderer = renderers[0]; Bounds localBounds = firstRenderer.localBounds; // 将子物体的世界空间中心点转换为父物体局部空间坐标 localBounds.center = transform.InverseTransformPoint(firstRenderer.bounds.center); // 考虑子物体自身缩放对包围盒大小的影响 localBounds.extents = Vector3.Scale(firstRenderer.localBounds.extents, firstRenderer.transform.localScale); // 合并剩余子物体的局部包围盒 for (int i = 1; i < renderers.Length; i++) { Renderer renderer = renderers[i]; Bounds childLocalBounds = renderer.localBounds; childLocalBounds.center = transform.InverseTransformPoint(renderer.bounds.center); childLocalBounds.extents = Vector3.Scale(renderer.localBounds.extents, renderer.transform.localScale); localBounds.Encapsulate(childLocalBounds); } return localBounds; }
步骤2:获取世界空间的同步外围点
基于局部包围盒,定义你需要的四个外围点(比如局部空间的左、右、前、后侧面中心点,或四个角点),再通过TransformPoint转换到世界空间——这个方法会自动应用父物体的旋转、缩放和位移,让点的位置完全跟随物体变换:
public List<Vector3> GetSyncedOuterPoints() { Bounds localBounds = GetLocalBounds(); List<Vector3> outerPoints = new List<Vector3>(); // 示例:获取局部包围盒的四个侧面中心点(可根据需求调整) Vector3 leftCenter = localBounds.center + Vector3.left * localBounds.extents.x; Vector3 rightCenter = localBounds.center + Vector3.right * localBounds.extents.x; Vector3 frontCenter = localBounds.center + Vector3.forward * localBounds.extents.z; Vector3 backCenter = localBounds.center + Vector3.back * localBounds.extents.z; // 转换为世界空间点 outerPoints.Add(transform.TransformPoint(leftCenter)); outerPoints.Add(transform.TransformPoint(rightCenter)); outerPoints.Add(transform.TransformPoint(frontCenter)); outerPoints.Add(transform.TransformPoint(backCenter)); // 如果你需要的是包围盒的四个角点,可替换为以下代码: // Vector3 cornerBLF = new Vector3(localBounds.min.x, localBounds.min.y, localBounds.max.z); // 左下前 // Vector3 cornerBRF = new Vector3(localBounds.max.x, localBounds.min.y, localBounds.max.z); // 右下前 // Vector3 cornerBLB = new Vector3(localBounds.min.x, localBounds.min.y, localBounds.min.z); // 左下后 // Vector3 cornerBRB = new Vector3(localBounds.max.x, localBounds.min.y, localBounds.min.z); // 右下后 // outerPoints.Add(transform.TransformPoint(cornerBLF)); // outerPoints.Add(transform.TransformPoint(cornerBRF)); // outerPoints.Add(transform.TransformPoint(cornerBLB)); // outerPoints.Add(transform.TransformPoint(cornerBRB)); return outerPoints; }
原理说明
- 世界空间的
Renderer.bounds是轴对齐的,无论物体怎么旋转,它的包围盒始终贴合世界坐标轴,所以无法反映物体自身的朝向。 - 局部空间的包围盒是以父物体的局部坐标系为基准的,再通过
transform.TransformPoint转换时,会自动叠加父物体的旋转、缩放和位移,最终得到的世界空间点会完全跟随物体的姿态变化。
内容的提问来源于stack exchange,提问作者MisterZeeba
相关产品推荐
相关产品推荐

