Here is my workaround of this problem for Unity version 2018 1.1f1.
I just check if there are adjacent bricks when we hit corner and if there any, correct velocity of the ball.
Ball.cs:
public class Ball : MonoBehaviour {
private Vector2 velocityBeforeCollision;
private void FixedUpdate()
{
velocityBeforeCollision = GetComponent<Rigidbody2D>().velocity;
}
private void OnCollisionEnter2D(Collision2D collision)
{
if (collision.collider.GetComponent<Brick>() && hasStarted) {
CorrectBounceVelocity(collision);
}
}
private void CorrectBounceVelocity(Collision2D collision) {
ContactPoint2D[] contactPoints = new ContactPoint2D[1];
collision.GetContacts(contactPoints);
Vector2 normal = contactPoints[0].normal;
// define points to check neighboring bricks
Vector2 checkPointRight = new Vector2(contactPoints[0].point.x + .1f, contactPoints[0].point.y);
Vector2 checkPointLeft = new Vector2(contactPoints[0].point.x - .1f, contactPoints[0].point.y);
Vector2 checkPointTop = new Vector2(contactPoints[0].point.x, contactPoints[0].point.y + .1f);
Vector2 checkPointBottom = new Vector2(contactPoints[0].point.x, contactPoints[0].point.y - .1f);
Collider2D neighborObject;
// check for each corner of brick
if (normal.x > 0 && normal.y > 0) // check if we hit top right corner
{
// non-orthogonal normal means that we hit corner
// check if any of 2 adjacent bricks presents
if (neighborObject = Physics2D.OverlapArea(checkPointRight, checkPointRight))
{
if (neighborObject.GetComponent<Brick>()) { // check if it is brick not ball
// if there is adjacent brick we correct ball velocity
GetComponent<Rigidbody2D>().velocity = new Vector2(velocityBeforeCollision.x, velocityBeforeCollision.y * -1);
}
}
if (neighborObject = Physics2D.OverlapArea(checkPointTop, checkPointTop))
{
if (neighborObject.GetComponent<Brick>())
{
GetComponent<Rigidbody2D>().velocity = new Vector2(velocityBeforeCollision.x * -1, velocityBeforeCollision.y);
}
}
}
else if (normal.x > 0 && normal.y < 0) // and so on for every other corner...
{
if (neighborObject = Physics2D.OverlapArea(checkPointRight, checkPointRight))
{
if (neighborObject.GetComponent<Brick>())
{
GetComponent<Rigidbody2D>().velocity = new Vector2(velocityBeforeCollision.x, velocityBeforeCollision.y * -1);
}
}
if (neighborObject = Physics2D.OverlapArea(checkPointBottom, checkPointBottom))
{
if (neighborObject.GetComponent<Brick>())
{
GetComponent<Rigidbody2D>().velocity = new Vector2(velocityBeforeCollision.x * -1, velocityBeforeCollision.y);
}
}
}
else if (normal.x < 0 && normal.y > 0)
{
if (neighborObject = Physics2D.OverlapArea(checkPointLeft, checkPointLeft))
{
if (neighborObject.GetComponent<Brick>())
{
GetComponent<Rigidbody2D>().velocity = new Vector2(velocityBeforeCollision.x, velocityBeforeCollision.y * -1);
}
}
if (neighborObject = Physics2D.OverlapArea(checkPointTop, checkPointTop))
{
if (neighborObject.GetComponent<Brick>())
{
GetComponent<Rigidbody2D>().velocity = new Vector2(velocityBeforeCollision.x * -1, velocityBeforeCollision.y);
}
}
}
else if (normal.x < 0 && normal.y < 0)
{
if (neighborObject = Physics2D.OverlapArea(checkPointLeft, checkPointLeft))
{
if (neighborObject.GetComponent<Brick>())
{
GetComponent<Rigidbody2D>().velocity = new Vector2(velocityBeforeCollision.x, velocityBeforeCollision.y * -1);
}
}
if (neighborObject = Physics2D.OverlapArea(checkPointBottom, checkPointBottom))
{
if (neighborObject.GetComponent<Brick>())
{
GetComponent<Rigidbody2D>().velocity = new Vector2(velocityBeforeCollision.x * -1, velocityBeforeCollision.y);
}
}
}
}
}