public void TestCollision() { CollisionInfo = Collisions.SphereCollision(PositionA, PositionB, VelocityA, VelocityB, RadiusA, RadiusB, Elastisity); if (CollisionInfo.Collided) { ShowGhostPositions = true; TestedCollision = true; GhostTime = CollisionInfo.Time; initalPosA = SphereA.position; initalPosB = SphereB.position; SphereA.position = CollisionInfo.CollisionCentreA; SphereB.position = CollisionInfo.CollisionCentreB; } else { Debug.Log("No Collision"); } }
public static SpheresCollisionInfo SphereCollision(Vector3 _positionA, Vector3 _positionB, Vector3 _velocityA, Vector3 _velocityB, float _radiusA, float _radiusB, float _elastisity) { var info = new SpheresCollisionInfo(); float sqrRadiiSum = (_radiusA + _radiusB) * (_radiusA + _radiusB); Vector3 offsetToB = _positionB - _positionA; // Already colliding if (offsetToB.sqrMagnitude <= sqrRadiiSum) { info.Collided = true; float resolutionDst = (_radiusA + _radiusB) - offsetToB.magnitude; info.CollisionCentreA = _positionA - offsetToB.normalized * resolutionDst / 2; info.CollisionCentreB = _positionB + offsetToB.normalized * resolutionDst / 2; return(info); } // Get velocity of A in the reference frame of B, such that B can be considered a stationary object Vector3 _velocityAInReferenceFrameOfB = _velocityA - _velocityB; // Can't collide if A moving away from B if (Vector3.Dot(_velocityAInReferenceFrameOfB, offsetToB) < 0) { return(info); } // Calculate the closest point of A passing B Vector3 dirAInReferenceFrameOfB = _velocityAInReferenceFrameOfB.normalized; Vector3 closestPassingPointToB = _positionA + dirAInReferenceFrameOfB * Vector3.Dot(dirAInReferenceFrameOfB, offsetToB); float closestSqrDstToBInPassing = (closestPassingPointToB - _positionB).sqrMagnitude; // Check if too far away to collide float resolveIntersectionSqrDst = sqrRadiiSum - closestSqrDstToBInPassing; if (resolveIntersectionSqrDst < 0) { return(info); } // Calculate backtrack distance to avoid intersection float resolveIntersectionDst = Mathf.Sqrt(resolveIntersectionSqrDst); Vector3 closestConstrainedPoint = closestPassingPointToB - resolveIntersectionDst * dirAInReferenceFrameOfB; float collisionTime = (closestConstrainedPoint - _positionA).magnitude / _velocityAInReferenceFrameOfB.magnitude; Vector3 distanceCenters = info.CollisionCentreA - info.CollisionCentreB; //Calculating the x direction velocity vector perpendicular to Y float distanceA = Vector3.Dot(distanceCenters.normalized, _velocityA); Vector3 velocityAX = distanceCenters.normalized * distanceA; Vector3 velocityAY = _velocityA - velocityAX; distanceCenters *= -1f; float distanceB = Vector3.Dot(distanceCenters.normalized, _velocityB); Vector3 velocityBX = distanceCenters.normalized * distanceB; Vector3 velocityBY = _velocityB - velocityBX; //if the collision is elastic the velocity after impact is the same as before so all we need to do is add our scalar to this function. //https://en.wikipedia.org/wiki/Elastic_collision //if we wanted to incorporate mass we need to change the velocity calculation to this. //info.VelocityAfterCollisionA = (velocityAX * (mass1 - mass2) / (mass1 + mass2) + velocityBX * (2 * mass2) / (mass1 + mass2) + velocityAY) * _elastisity; //info.VelocityAfterCollisionB = (velocityAX * (2 * mass1) / (mass1 + mass2) + velocityBX * (mass2 - ,ass1) / (mass1 + mass2) + velocityBY) * _elastisity; // Set collision info info.Collided = true; info.CollisionCentreA = _positionA + _velocityA * collisionTime; info.CollisionCentreB = _positionB + _velocityB * collisionTime; info.NormalCollisionPlane = (info.CollisionCentreA - info.CollisionCentreB).normalized; info.PointInCollisionPlane = (info.CollisionCentreB * _radiusB - info.CollisionCentreA * _radiusA); info.Time = collisionTime; //Simplified version because we are ignoring mass. info.VelocityAfterCollisionA = (velocityBX + velocityAY) * _elastisity; info.VelocityAfterCollisionB = (velocityAX + velocityBY) * _elastisity; return(info); }