//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); }
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); }