Thanks, Rick. Really enjoying this course so far.
Regarding the endless loop issue, I’ve been looking at the original Arkanoid game for possible solutions.
One thing I noticed is that the ball never ever travels perfectly horizontally or vertically. I replicated this behaviour by adding an OnCollisionExit2D callback to Ball.cs to make sure that the ball never bounces too close to these directions (within the range of a “fudge factor”).
Here’s the code I wrote. It seems to work quite well, and ensures that the ball always travels at the initial push speed to avoid unexpected slow-downs, which sometimes seemed to happen if the ball got stuck between the paddle and the left or right wall collider.
[Range(7.0f,15.0f)] [SerializeField] float pushSpeed = 12.0f;
[Range(0.2f, 0.9f)] [SerializeField] float bounceFudge = 0.4f;
private void OnCollisionExit2D(Collision2D collision)
{
// Prevent ball from following paths that are too close to horizontal
// or vertical (to prevent boring loops)
// Get the ball's velocity (after a bounce)
Vector2 ballVector = myRigidBody2D.velocity;
// Calculate the angle (in radians)
float ballAngle = Mathf.Atan2(ballVector.y, ballVector.x);
if (ballAngle >= 0.0f && ballAngle < bounceFudge) {
ballAngle = bounceFudge;
}
else if (ballAngle <= Mathf.PI * 0.5f && ballAngle > Mathf.PI * 0.5f - bounceFudge) {
ballAngle = Mathf.PI * 0.5f - bounceFudge;
}
else if (ballAngle > Mathf.PI * 0.5f && ballAngle < Mathf.PI * 0.5f + bounceFudge) {
ballAngle = Mathf.PI * 0.5f + bounceFudge;
}
else if (ballAngle <= Mathf.PI && ballAngle > Mathf.PI - bounceFudge) {
ballAngle = Mathf.PI - bounceFudge;
}
else if (ballAngle < bounceFudge - Mathf.PI) {
ballAngle = bounceFudge - Mathf.PI;
}
else if (ballAngle <= -Mathf.PI * 0.5f && ballAngle > -bounceFudge - Mathf.PI * 0.5f) {
ballAngle = -bounceFudge - Mathf.PI * 0.5f;
}
else if (ballAngle > -Mathf.PI * 0.5f && ballAngle < bounceFudge - Mathf.PI * 0.5f) {
ballAngle = bounceFudge - Mathf.PI * 0.5f;
}
else if (ballAngle < 0.0f && ballAngle > -bounceFudge) {
ballAngle = -bounceFudge;
}
else {
// If we didn't need to change the ball's path, just return...
return;
}
// ... But if we did need to change the path, update it now.
// NOTE: Also constrain the ball's velocity to its initial value
// to avoid unexpected changes of speed
ballVector.x = Mathf.Cos(ballAngle) * pushSpeed;
ballVector.y = Mathf.Sin(ballAngle) * pushSpeed;
myRigidBody2D.velocity = ballVector;
}