My fix for the Boring Ball Loops

To fix the boring ball loops I added the following function. I used mathf.Sign() to ensure the ball continued in the same direction.

private void CheckVelocity()
    {

        Vector2 currentVelocity = myRigidBody.velocity;
        if (Mathf.Abs(currentVelocity.y) < 1f)
        { 
            Vector2 newVelocity = new Vector2(currentVelocity.x, Mathf.Sign(currentVelocity.y) * 2f);
            myRigidBody.velocity = newVelocity;
        }

        if (Mathf.Abs(currentVelocity.x) < .25f)
        {
            Vector2 newVelocity = new Vector2(Mathf.Sign(currentVelocity.x) * 2f , currentVelocity.y);
            myRigidBody.velocity = newVelocity;
        }
    }

Then I added a timestamp to check for time since the last time the ball hit anything in order to check the velocities after the hit not during. I found that if the velocity was checked at the exact instant of impact then the velocities were near zero. I update the timestamp in the OnCollisionEnter2D function and then check that it has been .1 second since last hit with this if Statement in the Update function. I added the hitHasOccured test to prevent the CheckVelocity function from being called on every Update between the velocity corrections and the next hit.

 if (hitHasOccured && Time.timeSinceLevelLoad - timeSinceLastHit > .1f)
        {
            CheckVelocity();
            hitHasOccured = false;
        }

Edit: corrected some grammer

1 Like

Interesting solution. Mine is way more conservative. I also check on the exit of the collision, which is after the engine has calculated the new trajectory:

private void OnCollisionExit2D(Collision2D collision)
    {
        CheckForToxicTrajectory();
    }

    private void CheckForToxicTrajectory() //both functions are the same, different axis aside
    {
        CheckToxicXAxis();
        CheckToxicYAxis();
    }

    private void CheckToxicYAxis()
    {
        if (rigidbody2D.velocity.y < 2 && rigidbody2D.velocity.y > -2)
// from testing I found that velocities under those thresholds resulted in slow and boring loops
        {
            Debug.LogError("Corrected trajectory!"); //because I wanna know when this script runs
            if (rigidbody2D.velocity.y > 0)
            {
                rigidbody2D.velocity = new Vector2(rigidbody2D.velocity.x, 2.0f);
            }
            else rigidbody2D.velocity = new Vector2(rigidbody2D.velocity.x, -2.0f);
        }
    }

    private void CheckToxicXAxis()
    {
        if (rigidbody2D.velocity.x < 2 && rigidbody2D.velocity.x > -2)
        {
            Debug.LogError("Corrected trajectory!");
            if (rigidbody2D.velocity.x > 0)
            {
                rigidbody2D.velocity = new Vector2(2.0f, rigidbody2D.velocity.y);
            }
            else rigidbody2D.velocity = new Vector2(-2.0f, rigidbody2D.velocity.y);
        }
    }

I could add some random variation to the new trajectory but in practice noone will notice.

Privacy & Terms