Unity Bounds的理解

1.首先看unity api对Bounds的解释

An axis-aligned bounding box, or AABB for short, is a box aligned with coordinate axes and fully enclosing some object.  Because the box is never rotated with respect to the axes, it can be defined by just its center and extents, or alternatively by min and max points.

翻译:

轴对齐边框(简称AABB)是与坐标轴对齐并完全包围某个对象的框。 因为方框不会相对于坐标轴旋转,所以可以通过它的中心和范围来定义它,或者通过最小和最大点来定义它。

看完之后可能有的同学已经明白了它的涵义,有的同学还是一头问号。

反正我看完还是不明白 然后我就做了一些操作 用来明确它的涵义

首先我们先来看一下什么是轴对齐边框
按照api的解释: 它是一个与坐标轴对齐并且完全包围某个对象的框。


疑问:它是与哪一个坐标轴对齐?  完全包围的对象是谁?
我们带着这两个疑问往下看。

2.Bounds是一个结构体 他有一些属性 我们一起看一下

1.center 顾名思义 就是中心点。
2.extents 包围盒的范围。 这总是边界大小的一半。 
3.size 边界大小。
4.min 盒子的最小点 等于 center-extents。
5.max 盒子的最大点  等于 center+extents。

我们通过画线的方式分别看一下 各个参数在预制体上的位置。

Bounds bounds = this.GetComponent<Collider>().bounds;
Debug.DrawLine(bounds.center, bounds.center + bounds.extents, Color.red);

扫描二维码关注公众号,回复: 14724752 查看本文章

 

我们可以看到这个向量的长度是 从中心点到右上角的长度。

由于extents是size的一半, 所以 我们这样画size。

//得到左下角的位置
Vector3 p1 = bounds.center - bounds.extents;
Debug.DrawLine(p1, p1 + bounds.size, Color.green);

 

 我们可以看到size的长度刚好是从左下角到右上角的长度。

然后我们分别画出最小值 和 最大值和中心点的连线。

Debug.DrawLine(bounds.center,  bounds.min, Color.gray);

Debug.DrawLine(bounds.center, bounds.max, Color.cyan);

 

由此可以看出 最小值在左下角,最大值在右上角。

3.尝试旋转

然后 我们试着旋转一下这个小方块。

旋转之后我们发现这个最小值最大值 不再是小方块的 左下角右上角
换言之 他并不是和自身的坐标轴对齐


于是 我尝试着画出 这个小方块的Bounds

//后左下角
        Vector3 backBottomLeft = bounds.min;
        ///后右下角
        Vector3 backBottomRight = backBottomLeft + new Vector3(bounds.size.x, 0, 0);
        ///前左下角
        Vector3 forwardBottomLeft = backBottomLeft + new Vector3(0, 0, bounds.size.z);
        ///前右下角
        Vector3 forwardBottomRight = backBottomLeft + new Vector3(bounds.size.x, 0, bounds.size.z);
        ///后右上角
        Vector3 backTopRight = backBottomLeft + new Vector3(bounds.size.x, bounds.size.y, 0);
        ///前左上角
        Vector3 forwardTopLeft = backBottomLeft + new Vector3(0, bounds.size.y, bounds.size.z);
        ///后左上角
        Vector3 backTopLeft = backBottomLeft + new Vector3(0, bounds.size.y, 0);
        //前右上角
        Vector3 forwardTopRight = bounds.max;

        Debug.DrawLine(bounds.min, backBottomRight, Color.red);
        Debug.DrawLine(backBottomRight, forwardBottomRight, Color.red);
        Debug.DrawLine(forwardBottomRight, forwardBottomLeft, Color.red);
        Debug.DrawLine(forwardBottomLeft, bounds.min, Color.red);

        Debug.DrawLine(bounds.min, backTopLeft, Color.red);
        Debug.DrawLine(backBottomRight, backTopRight, Color.red);
        Debug.DrawLine(forwardBottomRight, bounds.max, Color.red);
        Debug.DrawLine(forwardBottomLeft, forwardTopLeft, Color.red);

        Debug.DrawLine(backTopRight, backTopLeft, Color.red);
        Debug.DrawLine(backTopLeft, forwardTopLeft, Color.red);
        Debug.DrawLine(forwardTopLeft, bounds.max, Color.red);
        Debug.DrawLine(bounds.max, backTopRight, Color.red);

运行结果如下:
当小方块完全不做旋转时 本地坐标轴和世界坐标轴重合

 

 旋转45度之后

注:红框是我们画出的小方块的Bounds

我们发现小方块的Bounds没有随着小方块旋转 但是它仍然完全包裹着小方块

由此 我们疑问解开
即是:
它是与世界坐标轴对齐   完全包围的对象是它自身的预制体

完整代码如下:

public class BoundsTest : MonoBehaviour {
    void Start() {

    }

    // Update is called once per frame
    void Update() {

        Bounds bounds = this.GetComponent<Collider>().bounds;
        //bounds.extents 中心点到角的向量
        Debug.DrawLine(bounds.center, bounds.center + bounds.extents, Color.red);
        //bounds.size从左下角到右上角的向量
        //得到左下角的位置
        Vector3 p1 = bounds.center - bounds.extents;
        Debug.DrawLine(p1, p1 + bounds.size, Color.green);
        //bounds.min
        Debug.DrawLine(bounds.center,  bounds.min, Color.gray);
        //bounds.max 
        Debug.DrawLine(bounds.center, bounds.max, Color.cyan);
        //后左下角
        Vector3 backBottomLeft = bounds.min;
        ///后右下角
        Vector3 backBottomRight = backBottomLeft + new Vector3(bounds.size.x, 0, 0);
        ///前左下角
        Vector3 forwardBottomLeft = backBottomLeft + new Vector3(0, 0, bounds.size.z);
        ///前右下角
        Vector3 forwardBottomRight = backBottomLeft + new Vector3(bounds.size.x, 0, bounds.size.z);
        ///后右上角
        Vector3 backTopRight = backBottomLeft + new Vector3(bounds.size.x, bounds.size.y, 0);
        ///前左上角
        Vector3 forwardTopLeft = backBottomLeft + new Vector3(0, bounds.size.y, bounds.size.z);
        ///后左上角
        Vector3 backTopLeft = backBottomLeft + new Vector3(0, bounds.size.y, 0);
        //前右上角
        Vector3 forwardTopRight = bounds.max;

        Debug.DrawLine(bounds.min, backBottomRight, Color.red);
        Debug.DrawLine(backBottomRight, forwardBottomRight, Color.red);
        Debug.DrawLine(forwardBottomRight, forwardBottomLeft, Color.red);
        Debug.DrawLine(forwardBottomLeft, bounds.min, Color.red);

        Debug.DrawLine(bounds.min, backTopLeft, Color.red);
        Debug.DrawLine(backBottomRight, backTopRight, Color.red);
        Debug.DrawLine(forwardBottomRight, bounds.max, Color.red);
        Debug.DrawLine(forwardBottomLeft, forwardTopLeft, Color.red);

        Debug.DrawLine(backTopRight, backTopLeft, Color.red);
        Debug.DrawLine(backTopLeft, forwardTopLeft, Color.red);
        Debug.DrawLine(forwardTopLeft, bounds.max, Color.red);
        Debug.DrawLine(bounds.max, backTopRight, Color.red);

    }
}

有兴趣的可以自己跟着画一下

另外拓展一下包围盒
1.aabb包围盒 Bounds就属于aabb包围盒 他是无向的 检测精度较差
2.obb包围盒 boxCollider属于obb包围盒 他是有向的 检测精度较好
另外还有包围球/固定方向凸包 有兴趣的同学可以自行了解一下。

猜你喜欢

转载自blog.csdn.net/SmillCool/article/details/126708371
今日推荐