获取BoxCollider的真实边界(非Bounds)

之前使用的方法是:

    bool PosInBounds(Transform trans,Bounds bounds)
    {
        return bounds.Contains(transform.position);
    }

一句话就搞定了,但是!

在开发防穿过程中发现使用BoxCollider的Bounds有问题:

当BoxCollider有旋转角度的时候,Bounds会比实际的BoxCollider范围大。

如下图:

 

 

所以决定自己算一下边界:

    public Vector3[] GetBoxPoints(Collider collider)
    {

        Vector3[] allPoints = new Vector3[8];

        Quaternion quaternion = collider.transform.rotation;

        BoxCollider boxCollider = null;
        try
        {
            boxCollider = (BoxCollider)collider;
        }
        catch
        {
            return new Vector3[0];
        }
        Vector3 c = collider.bounds.center;
        Vector3 size = new Vector3(boxCollider.size.x * boxCollider.transform.lossyScale.x, boxCollider.size.y * boxCollider.transform.lossyScale.y, boxCollider.size.z * boxCollider.transform.lossyScale.z);
        float rx = size.x / 2f;
        float ry = size.y / 2f;
        float rz = size.z / 2f;

        allPoints[0] = c + quaternion * new Vector3(-rx, -ry, rz);
        allPoints[1] = c + quaternion * new Vector3(rx, -ry, rz);
        allPoints[2] = c + quaternion * new Vector3(rx, -ry, -rz);
        allPoints[3] = c + quaternion * new Vector3(-rx, -ry, -rz);

        allPoints[4] = c + quaternion * new Vector3(-rx, ry, rz);
        allPoints[5] = c + quaternion * new Vector3(rx, ry, rz);
        allPoints[6] = c + quaternion * new Vector3(rx, ry, -rz);
        allPoints[7] = c + quaternion * new Vector3(-rx, ry, -rz);
        return allPoints;
    }

要是想看到边界可以在Scene场景绘制出来:

    void DrawLine(Collider collider)
    {
        Vector3[] points = GetBoxPoints(collider);
        if (points.Length == 0)
        {
            return;
        }
        #region 底面
        Debug.DrawLine(points[0], points[1], Color.red);
        Debug.DrawLine(points[1], points[2], Color.red);
        Debug.DrawLine(points[2], points[3], Color.red);
        Debug.DrawLine(points[0], points[3], Color.red);
        #endregion

        #region 顶面
        Debug.DrawLine(points[4], points[5], Color.red);
        Debug.DrawLine(points[5], points[6], Color.red);
        Debug.DrawLine(points[6], points[7], Color.red);
        Debug.DrawLine(points[4], points[7], Color.red);
        #endregion

        Debug.DrawLine(points[0], points[4], Color.red);
        Debug.DrawLine(points[1], points[5], Color.red);
        Debug.DrawLine(points[2], points[6], Color.red);
        Debug.DrawLine(points[3], points[7], Color.red);
    }

画出来后如图:

 

黄色和绿色的线重叠后显示了黄色。 

这就为判断边界提供了依据。

获取到八个顶点后计算围成立方体的6个面:

    public bool PosInBounds(Transform trans,Collider collider)
    {
        Vector3[] points = GetBoxPoints(collider);

        Plane forward = new Plane(points[0], points[1], points[2]);
        Plane back = new Plane(points[4], points[5], points[6]);
        Plane left = new Plane(points[3], points[2], points[6]);
        Plane right = new Plane(points[0], points[1], points[5]);
        Plane up = new Plane(points[3], points[0], points[4]);
        Plane down = new Plane(points[2], points[1], points[5]);

        bool isEnterForwardBack = forward.GetSide(trans.position) != back.GetSide(trans.position);
        bool isEnterLeftRight = left.GetSide(trans.position) != right.GetSide(trans.position);
        bool isEnterUpDown = up.GetSide(trans.position) != down.GetSide(trans.position);

        return isEnterForwardBack && isEnterLeftRight && isEnterUpDown;

    }

获取6个面后,直接判断:

  点是不是在两个相对的面中间,即可知道是不是在BoxCollider中。

 

 

实际应用中可以用来计算人物移动、摄像机移动防穿透。

 

posted @ 2020-04-22 17:40  有只小耗子  阅读(1103)  评论(0编辑  收藏  举报