コード例 #1
0
    void DrawSelectedObject()
    {
        if (_lineMaterial == null)
        {
            return;
        }

        NewBoxCollider box = _selectedObject.GetComponent <NewBoxCollider> ();

        if (box != null)
        {
            DrawCube(box.origin.dots, 1f);
            DrawCube(box.origin.dots, 1.0005f);
            DrawCube(box.origin.dots, 1.0006f);
            DrawCube(box.origin.dots, 1.0007f);
            DrawCube(box.origin.dots, 1.0008f);

            return;
        }

        NewSphereCollider sphere = _selectedObject.GetComponent <NewSphereCollider> ();

        if (sphere != null)
        {
            DrawSphere(sphere.radius, sphere.transform.position);

            return;
        }
    }
コード例 #2
0
 public bool BoxToBox(NewBoxCollider boxA, NewBoxCollider boxB)
 {
     // reference https://developer.mozilla.org/en-US/docs/Games/Techniques/3D_collision_detection
     // If all boxA axis are inside boxB then there is a collision
     return((boxA.minBounds.x < boxB.maxBounds.x && boxA.maxBounds.x > boxB.minBounds.x) &&
            (boxA.minBounds.y < boxB.maxBounds.y && boxA.maxBounds.y > boxB.minBounds.y) &&
            (boxA.minBounds.z < boxB.maxBounds.z && boxA.maxBounds.z > boxB.minBounds.z));
 }
コード例 #3
0
    public bool SphereToBox(NewSphereCollider sphere, NewBoxCollider box)
    {
        // reference https://developer.mozilla.org/en-US/docs/Games/Techniques/3D_collision_detection

        // find the closest point on the box to the center of the sphere
        Vector3 closestPoint = Vector3.zero;

        closestPoint.x = Mathf.Max(box.minBounds.x, Mathf.Min(sphere.transform.position.x, box.maxBounds.x));
        closestPoint.y = Mathf.Max(box.minBounds.y, Mathf.Min(sphere.transform.position.y, box.maxBounds.y));
        closestPoint.z = Mathf.Max(box.minBounds.z, Mathf.Min(sphere.transform.position.z, box.maxBounds.z));

        // distance between closest point and center of the sphere
        float distance = Mathf.Sqrt(
            (closestPoint.x - sphere.transform.position.x) * (closestPoint.x - sphere.transform.position.x) +
            (closestPoint.y - sphere.transform.position.y) * (closestPoint.y - sphere.transform.position.y) +
            (closestPoint.z - sphere.transform.position.z) * (closestPoint.z - sphere.transform.position.z));

        return(distance < sphere.radius);
    }
コード例 #4
0
    public CollisionData BoxToBoxManifold(NewBoxCollider boxA, NewBoxCollider boxB)
    {
        // reference: https://gamedevelopment.tutsplus.com/tutorials/how-to-create-a-custom-2d-physics-engine-the-basics-and-impulse-resolution--gamedev-6331
        // NOTE that I had to convert from 2D to 3D and add my own stuff (the tutorial wasn't entirely accurate)

        // Manifold Initialisation
        CollisionData manifold = new CollisionData();

        manifold.bodyA       = boxA.transform.gameObject.GetComponent <NewRigidBody> ();
        manifold.bodyB       = boxB.transform.gameObject.GetComponent <NewRigidBody> ();
        manifold.bodyAobj    = boxA.transform.gameObject;
        manifold.bodyBobj    = boxB.transform.gameObject;
        manifold.normal      = Vector3.zero;
        manifold.penetration = 0.0f;

        // Exit if there is not a collision
        manifold.wasCollision = BoxToBox(boxA, boxB);
        if (manifold.wasCollision == false)
        {
            return(manifold);
        }

        Vector3 relativePosition = boxB.transform.position - boxA.transform.position;
        float   xOverlap         = boxA.extents.x + boxB.extents.x - Mathf.Abs(relativePosition.x);

        // If overlapping in the x-axis
        if (xOverlap > 0.0f)
        {
            float yOverlap = boxA.extents.y + boxB.extents.y - Mathf.Abs(relativePosition.y);

            // If also overlapping on the y-axis
            if (yOverlap > 0.0f)
            {
                float zOverlap = boxA.extents.z + boxB.extents.z - Mathf.Abs(relativePosition.z);

                // Find axis of least penetration
                if (xOverlap < yOverlap && xOverlap < zOverlap)
                {
                    if (relativePosition.x < 0.0f)
                    {
                        manifold.normal = new Vector3(-1.0f, 0.0f, 0.0f);
                    }
                    else
                    {
                        manifold.normal = new Vector3(1.0f, 0.0f, 0.0f);
                    }

                    manifold.penetration = xOverlap;
                }
                else if (yOverlap <= xOverlap && yOverlap < zOverlap)
                {
                    if (relativePosition.y < 0.0f)
                    {
                        manifold.normal = new Vector3(0.0f, -1.0f, 0.0f);
                    }
                    else
                    {
                        manifold.normal = new Vector3(0.0f, 1.0f, 0.0f);
                    }

                    manifold.penetration = yOverlap;
                }
                else
                {
                    if (relativePosition.z < 0.0f)
                    {
                        manifold.normal = new Vector3(0.0f, 0.0f, -1.0f);
                    }
                    else
                    {
                        manifold.normal = new Vector3(0.0f, 0.0f, 1.0f);
                    }

                    manifold.penetration = zOverlap;
                }
            }
        }

        return(manifold);
    }
コード例 #5
0
    public CollisionData BoxToBoxSAT(NewBoxCollider boxA, NewBoxCollider boxB)
    {
        // reference to seperating axis theorem:
        // https://gamedevelopment.tutsplus.com/tutorials/collision-detection-using-the-separating-axis-theorem--gamedev-169
        // 3D axis found using: https://gamedev.stackexchange.com/questions/44500/how-many-and-which-axes-to-use-for-3d-obb-collision-with-sat
        CollisionData manifold = new CollisionData();

        manifold.wasCollision = false;

        if (boxA == null || boxB == null)
        {
            return(manifold);
        }

        manifold.bodyA       = boxA.transform.gameObject.GetComponent <NewRigidBody>();
        manifold.bodyB       = boxB.transform.gameObject.GetComponent <NewRigidBody>();
        manifold.bodyAobj    = boxA.transform.gameObject;
        manifold.bodyBobj    = boxB.transform.gameObject;
        manifold.normal      = Vector3.zero;
        manifold.penetration = 0.0f;


        // dots
        List <Vector3> boxADots = new List <Vector3> ();
        List <Vector3> boxBDots = new List <Vector3> ();

        for (int i = 0; i < boxA.origin.dots.Length; i++)
        {
            boxADots.Add(boxA.origin.dots [i]);
            boxBDots.Add(boxB.origin.dots [i]);
        }

        // normals
        List <Vector3> boxANormals = new List <Vector3> ();
        List <Vector3> boxBNormals = new List <Vector3> ();

        for (int i = 1; i < 3; i++)
        {
            boxANormals.Add(boxA.origin.normals[i]);
            boxBNormals.Add(boxB.origin.normals [i]);
        }
        boxANormals.Add(boxA.faces [1].normals [0]);
        boxBNormals.Add(boxB.faces [1].normals [0]);



        _currentStateDebug.Clear();

        // Optimisation
        if (Vector3.Distance(boxA.transform.position, boxB.transform.position) > 10.0f)
        {
            return(manifold);
        }

        // Box 1 XYZ
        bool seperate_Q = isSeperate(boxADots, boxBDots, boxANormals[0], boxB.transform.name);
        bool seperate_P = isSeperate(boxADots, boxBDots, boxANormals[1], boxB.transform.name);
        bool seperate_5 = isSeperate(boxADots, boxBDots, boxANormals[2], boxB.transform.name);

        // Box 2 XYZ
        bool seperate_S = isSeperate(boxADots, boxBDots, boxBNormals[0], boxB.transform.name);
        bool seperate_R = isSeperate(boxADots, boxBDots, boxBNormals[1], boxB.transform.name);
        bool seperate_6 = isSeperate(boxADots, boxBDots, boxBNormals[2], boxB.transform.name);

        // Cross Products
        bool seperate_7 = isSeperate(boxADots, boxBDots, Vector3.Cross(boxANormals[0], boxBNormals[0]), boxB.transform.name);
        bool seperate_8 = isSeperate(boxADots, boxBDots, Vector3.Cross(boxANormals[0], boxBNormals[1]), boxB.transform.name);
        bool seperate_9 = isSeperate(boxADots, boxBDots, Vector3.Cross(boxANormals[0], boxBNormals[2]), boxB.transform.name);

        bool seperate_10 = isSeperate(boxADots, boxBDots, Vector3.Cross(boxANormals[1], boxBNormals[0]), boxB.transform.name);
        bool seperate_11 = isSeperate(boxADots, boxBDots, Vector3.Cross(boxANormals[1], boxBNormals[1]), boxB.transform.name);
        bool seperate_12 = isSeperate(boxADots, boxBDots, Vector3.Cross(boxANormals[1], boxBNormals[2]), boxB.transform.name);

        bool seperate_13 = isSeperate(boxADots, boxBDots, Vector3.Cross(boxANormals[2], boxBNormals[0]), boxB.transform.name);
        bool seperate_14 = isSeperate(boxADots, boxBDots, Vector3.Cross(boxANormals[2], boxBNormals[1]), boxB.transform.name);
        bool seperate_15 = isSeperate(boxADots, boxBDots, Vector3.Cross(boxANormals[2], boxBNormals[2]), boxB.transform.name);


        // If one is seperate then no collision
        manifold.wasCollision = !(seperate_10 || seperate_11 || seperate_12 || seperate_13 || seperate_14 || seperate_15 || seperate_5 || seperate_6 || seperate_7 || seperate_8 || seperate_9 ||
                                  seperate_P || seperate_Q || seperate_R || seperate_S);


        if (manifold.wasCollision == true)
        {
            if (_previousStateDebug.Length > 0)
            {
                // Find penertration, normal and contact point
                Vector3 checkPoint = _previousStateDebug [0].faceA - Vector3.Scale(-manifold.normal / 2.0f, boxB.extents);
                manifold.penetration = Vector3.Distance(checkPoint, _previousStateDebug[0].faceA);

                manifold.normal = -_previousStateDebug [0].axis;

                manifold.contacts = new List <Vector3> ();
                for (int contactI = 0; contactI < _previousStateDebug.Length; contactI++)
                {
                    manifold.contacts.Add(_previousStateDebug [contactI].faceA);
                }
            }
            else
            {
                Debug.LogWarning("No contact between? " + boxA.transform.name + "," + boxB.transform.name);
            }
        }
        else
        {
            _previousStateDebug = new SeperationDataDebug[_currentStateDebug.Count];
            _currentStateDebug.CopyTo(_previousStateDebug);
            _currentStateDebug.Clear();
        }


        return(manifold);
    }
コード例 #6
0
    public CollisionData BoxToSphereManifold(NewBoxCollider box, NewSphereCollider sphere)
    {
        // reference: https://gamedevelopment.tutsplus.com/tutorials/how-to-create-a-custom-2d-physics-engine-the-basics-and-impulse-resolution--gamedev-6331
        // (NOTE reference is in 2d, had to add 3D as well as my own manifold stuff)

        // Initialise manifold
        CollisionData manifold = new CollisionData();

        manifold.bodyA        = box.transform.gameObject.GetComponent <NewRigidBody> ();
        manifold.bodyB        = sphere.transform.gameObject.GetComponent <NewRigidBody> ();
        manifold.bodyAobj     = box.transform.gameObject;
        manifold.bodyBobj     = sphere.transform.gameObject;
        manifold.normal       = Vector3.zero;
        manifold.penetration  = 0.0f;
        manifold.wasCollision = false;


        Vector3 relativePosition = sphere.transform.position - box.transform.position;

        // Closest point on A to center of B
        Vector3 closestPoint = Vector3.zero;

        closestPoint.x = Mathf.Max(box.minBounds.x, Mathf.Min(sphere.transform.position.x, box.maxBounds.x));
        closestPoint.y = Mathf.Max(box.minBounds.y, Mathf.Min(sphere.transform.position.y, box.maxBounds.y));
        closestPoint.z = Mathf.Max(box.minBounds.z, Mathf.Min(sphere.transform.position.z, box.maxBounds.z));


        // If Circle is inside Box
        bool inside = false;

        if (relativePosition == closestPoint)
        {
            inside = true;

            // Find closest axis
            if (Mathf.Abs(relativePosition.x) > Mathf.Abs(relativePosition.y) && Mathf.Abs(relativePosition.x) > Mathf.Abs(relativePosition.z))
            {
                // Clamp to closest extent
                if (closestPoint.x > 0.0f)
                {
                    closestPoint.x = box.extents.x;
                }
                else
                {
                    closestPoint.x = -box.extents.x;
                }
            }
            // y-axis is shorter
            else if (Mathf.Abs(relativePosition.y) > Mathf.Abs(relativePosition.z))
            {
                // Clamp to closest extent
                if (closestPoint.y > 0.0f)
                {
                    closestPoint.y = box.extents.y;
                }
                else
                {
                    closestPoint.y = -box.extents.y;
                }
            }
            // z-axis is shorter
            else
            {
                // Clamp to closest extent
                if (closestPoint.z > 0.0f)
                {
                    closestPoint.z = box.extents.z;
                }
                else
                {
                    closestPoint.z = -box.extents.z;
                }
            }
        }


        Vector3 normal = sphere.transform.position - closestPoint;

        float distance = (closestPoint.x - sphere.transform.position.x) * (closestPoint.x - sphere.transform.position.x) +
                         (closestPoint.y - sphere.transform.position.y) * (closestPoint.y - sphere.transform.position.y) +
                         (closestPoint.z - sphere.transform.position.z) * (closestPoint.z - sphere.transform.position.z);


        // If no collision then return
        manifold.wasCollision = (Mathf.Sqrt(distance) < sphere.radius);
        if (manifold.wasCollision == false)
        {
            return(manifold);
        }


        distance = Mathf.Sqrt(distance);


        // Flip collision normal if inside
        if (inside == true)
        {
            manifold.normal = Vector3.Normalize(-normal);
        }
        else
        {
            manifold.normal = Vector3.Normalize(normal);
        }


        manifold.penetration = sphere.radius - distance;

        // Contact point
        manifold.contacts = new List <Vector3> ();
        manifold.contacts.Add(closestPoint);

        return(manifold);
    }