Unity3D box与sphere碰撞

测试碰撞的时候,最好单独建立一个Demo(有点像单元测试),排除不必要的干扰,往往效更快,思路更清晰。
http://www.idivecat.com/archives/507
《实时碰撞算法检测》P113

在这里插入图片描述

注意

  • Bounds并不是碰撞体的参数集合,只是一个与坐标轴对齐的AABB盒,不会受到旋转的影响,因此不能作为碰撞的参数
  • InverseTransformVector会受到localScale的影响,因此需要乘以Scale或lossyScale
  • 本地变量和全局变量不要穿插引用,要统一,否则会出问题
public class CubeTest : MonoBehaviour
{
    public SphereCollider SphereCollider;
    public BoxCollider BoxCollider;

    // Start is called before the first frame update
    void Start()
    {
        
    }


    /// <summary>
    /// 点到OBB的最近点
    /// </summary>
    private Vector3 ClosestPointOBB(Vector3 p, BoxCollider boxCollider)
    {
        Vector3 extents = Vector3.Scale( boxCollider.transform.lossyScale, boxCollider.size) * 0.5f;
        Vector3 d = p - boxCollider.transform.position;
        Vector3 q = boxCollider.transform.position;

        // world space to local space
        Vector3 dl = boxCollider.InverseTransformVector(d);
        dl = Vector3.Scale(dl, boxCollider.transform.lossyScale);

        float distX = dl.x;   
        if (distX > extents.x) distX = extents.x;  
        if (distX < -extents.x) distX = -extents.x;
        // along the axis to get world position
        q += distX * boxCollider.transform.right;

        float distY = dl.y;
        if (distY > extents.y) distY = extents.y;
        if (distY < -extents.y) distY = -extents.y;
        q += distY * boxCollider.transform.up;

        float distZ = dl.z;
        if (distZ > extents.z) distZ = extents.z;
        if (distZ < -extents.z) distZ = -extents.z;
        q += distZ * boxCollider.transform.forward;

        return q;
    }

    /// <summary>
    /// 测试球与OBB相交,并取最近点
    /// </summary>
    private bool TestSphereOBB(SphereCollider s, BoxCollider boxCollider, ref Vector3 p)
    {
        p = ClosestPointOBB(s.transform.position, boxCollider);
        Vector3 v = p - s.transform.position;
        return Vector3.Dot(v, v) <= s.radius * s.radius;
    }


    // Update is called once per frame
    void Update()
    {
        Vector3 p = Vector3.zero;
        bool bCollide = TestSphereOBB(SphereCollider, BoxCollider, ref p);
        if (bCollide)
        {
            transform.GetComponent<Renderer>().material.color = Color.red;
        }
        else
        {
            transform.GetComponent<Renderer>().material.color = Color.white;
        }
    }


    private void OnDrawGizmos()
    {
        Vector3 q = ClosestPointOBB(SphereCollider.transform.position, BoxCollider);
        Gizmos.color = Color.green;
        Gizmos.DrawWireSphere(q, 0.1f);
    }
}

发布了258 篇原创文章 · 获赞 45 · 访问量 22万+

猜你喜欢

转载自blog.csdn.net/A13155283231/article/details/105429331