示例#1
0
    //bool weil schauen ob collision überhaupt da ist
    public bool CalculateCollisionData(PhysicsBodySphere bodyA, PhysicsBodySphere bodyB, ref Vector2 contactPoint, ref Vector2 contactNormal, ref float penetrationDepth)
    {
        Vector2 centerA        = bodyA.GetCenter();
        Vector2 centerB        = bodyB.GetCenter();
        Vector2 centerDelta    = centerB - centerA;
        float   combinedRadius = bodyA.radius + bodyB.radius;

        //check if sie kollidieren
        if (centerDelta.sqrMagnitude <= combinedRadius * combinedRadius) // quadrieren weil centera-centerb auch squared ist
        {
            //man braucht Contact normal, conctact point, penetration depth
            //Contact normal
            contactNormal = centerDelta.normalized; //gibt die richtung an in denen sie zusammenstecken

            //Penetration Depth
            //center delta, davon die magnitude, dann weiss man wie weit die zentren von einander entfernt sind, und man weiss auch den radius von beiden also weiss man wie wiet sie auseinander sein könnten bevor sie kollidieren
            penetrationDepth = combinedRadius - centerDelta.magnitude;

            //Vektor richtung andere sphere * den radius - der penetrationdepth durch 2
            contactPoint = centerA + contactNormal * (bodyA.radius - penetrationDepth * 0.5f); //dann genau der punkt der in der mitte liegt von der überlappung

            //Debug.DrawRay(contactPoint, contactNormal, Color.magenta);
            //Debug.Log("IS COLLIDING");
            return(true);
        }

        return(false);
    }
示例#2
0
    public bool CalculateCollisionData(PhysicsBodySphere bodyA, RectangleBody bodyB, ref Vector2 contactPoint, ref Vector2 contactNormal, ref float penetrationDepth)
    {
        //center a in den local space from rectangle bekommen, viel leichter zu berechnen wenn man sichs im lokal space vorstellt, weil das rectangle dann axis aligned ist, un dman spart sich viele vektor berechenungen, skalarprodukte etc.
        //die rotation zurücksetzen und dann wieder zurückdrehen, deswegen mal -bodyB.rotation
        Vector2 centerA = PhysicsBody.RotateVector2(bodyA.GetCenter() - bodyB.GetCenter(), -bodyB.rotation); //wie weit center von sphere vom center vom rectangle entfernt ist

        //vergrößerte bounding box (extents) um zu checken obs innerhalb oder außerhalb liegt, bei den faces workeds, aber bei den ecken dann nichtmehr, da braucht man noch einen check
        Vector2 inflatedExtents = bodyB.extent + Vector2.one * bodyA.radius;

        //jetzt checken ob centerA (den sphere mittelpunkt) innerhalb von diesen inflatedExtents liegt, es kann aber immer noch in den ecken liegen!
        if (centerA.x <= inflatedExtents.x /*zumindest nicht rechts von der box*/ && centerA.x >= -inflatedExtents.x /*nicht links von der box*/ &&
            centerA.y <= inflatedExtents.y && centerA.y >= -inflatedExtents.y)
        {
            //Check ob wir in den ecken liegen
            //absolut wert von x und y
            Vector2 absolutCenterA = new Vector2(Mathf.Abs(centerA.x), Mathf.Abs(centerA.y));

            if (absolutCenterA.x >= bodyB.extent.x && absolutCenterA.y >= bodyB.extent.y)          //wenn wir in dem rechteck (ecke) liegen
            {
                if ((absolutCenterA - bodyB.extent).sqrMagnitude <= bodyA.radius * bodyA.radius)   //ob wir wirklich mit der ecke collidieren
                {
                    Vector2 mirrorDir = new Vector2(Mathf.Sign(centerA.x), Mathf.Sign(centerA.y)); //mathf.Sign liefert +1, -1, oder 0 zurück, kommt drauf an was der input war z.B. 10 = 1, -5 = -1 usw.
                    //nur für ++ space also oberes viertel, deswegen y achse -1 multiplizieren zum spiegeln
                    contactPoint     = bodyB.extent;
                    contactNormal    = (contactPoint - absolutCenterA).normalized * mirrorDir;                                 //* mirrorDir weil es druaf ankommt in welcher ecke es liegt
                    contactPoint    *= mirrorDir;
                    penetrationDepth = bodyA.radius - (absolutCenterA - bodyB.extent) /* hier ist man rechts oben*/.magnitude; //magnitude weil man will die tatsächliche distanz haben

                    //radius - die distanz von center zum point --> da bekommt man die pendepth

                    //jetzt wieder in den World space !!!
                    contactPoint = bodyB.GetCenter() + PhysicsBody.RotateVector2(contactPoint, bodyB.rotation); /*local contactpoint muss rotiert werden */
                    //normalized Vector muss rotiert werden
                    contactNormal = PhysicsBody.RotateVector2(contactNormal, bodyB.rotation);
                    return(true);
                }
                else
                {
                    return(false);
                }
            }
            //Berechnung ob es an den flächen links rechts oben unten liegt, und nicht in den ecken
            //RIGHT
            else if (centerA.x > bodyB.extent.x)
            {
                //hier wieder in local space, ContactPoint bie face to face is in der mitte (kann auf der edge sein, oder der punkt der am weitesten drin is
                contactPoint     = new Vector2((bodyB.extent.x + centerA.x - bodyA.radius) * 0.5f /*mittelwert*/, centerA.y);
                contactNormal    = Vector2.left; //weil wir rechts liegen
                penetrationDepth = Mathf.Abs(bodyB.extent.x - (centerA.x - bodyA.radius));

                //weider in world space
                contactPoint  = bodyB.GetCenter() + PhysicsBody.RotateVector2(contactPoint, bodyB.rotation);
                contactNormal = PhysicsBody.RotateVector2(contactNormal, bodyB.rotation);
                return(true);
            }
            //Left
            else if (centerA.x < -bodyB.extent.x)
            {
                contactPoint     = new Vector2((-bodyB.extent.x + centerA.x + bodyA.radius) * 0.5f /*mittelwert*/, centerA.y);
                contactNormal    = Vector2.right;
                penetrationDepth = Mathf.Abs(-bodyB.extent.x - (centerA.x + bodyA.radius));

                contactPoint  = bodyB.GetCenter() + PhysicsBody.RotateVector2(contactPoint, bodyB.rotation);
                contactNormal = PhysicsBody.RotateVector2(contactNormal, bodyB.rotation);
                return(true);
            }
            //UP
            else if (centerA.y > bodyB.extent.y)
            {
                contactPoint     = new Vector2(centerA.x, (bodyB.extent.y + centerA.y - bodyA.radius) * 0.5f);
                contactNormal    = Vector2.down;
                penetrationDepth = Mathf.Abs(bodyB.extent.y - (centerA.y - bodyA.radius));

                contactPoint  = bodyB.GetCenter() + PhysicsBody.RotateVector2(contactPoint, bodyB.rotation);
                contactNormal = PhysicsBody.RotateVector2(contactNormal, bodyB.rotation);
                return(true);
            }
            //Down
            else if (centerA.y < -bodyB.extent.y)
            {
                contactPoint     = new Vector2(centerA.x, (-bodyB.extent.y + centerA.y + bodyA.radius) * 0.5f);
                contactNormal    = Vector2.up;
                penetrationDepth = Mathf.Abs(-bodyB.extent.y - (centerA.y + bodyA.radius));

                contactPoint  = bodyB.GetCenter() + PhysicsBody.RotateVector2(contactPoint, bodyB.rotation);
                contactNormal = PhysicsBody.RotateVector2(contactNormal, bodyB.rotation);
                return(true);
            }
            else
            {
                return(false);
            }
        }
        return(false);
    }