獲取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中。

 

 

實際應用中可以用來計算人物移動、攝像機移動防穿透。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM