How do I keep the ball bouncing forever?

In my project, I have a setup with a ball bouncing around a roughly square arena. The ball’s bouncing is controlled by this script.

using UnityEngine;

public class Bounce : MonoBehaviour{
	public Vector3 startSpeed;
    public float minSpeed;
    public float maxSpeed;
	
    private Rigidbody rb;
    private Vector3 velocity;
	
    // Start is called once before the first execution of Update after the MonoBehaviour is created
    void Start(){
        rb = GetComponent<Rigidbody>();
        rb.linearVelocity = startSpeed;
    }

    // Update is called once per frame
    void Update(){
		velocity = rb.linearVelocity;
    }

    void OnCollisionEnter(Collision collision){
        float speedmult = Random.Range(1,1.1f);
        float speed = Mathf.Clamp(velocity.magnitude * speedmult,minSpeed,maxSpeed);
        Vector3 direction = Vector3.Reflect(velocity.normalized, collision.contacts[0].normal);
        rb.linearVelocity = direction * speed;
		
		if(collision.GetContact(0).point.y < rb.position.y - (0.35f * transform.localScale.y)){
			rb.AddForce(0,0.5f,0,ForceMode.Impulse);
		}
    }
}

When the ball hits a corner, it sometimes starts rolling on the ground instead of bouncing. I don’t want that to happen. Is there any way to improve the code to keep the ball bouncing?

If you have a target velocity in mind, just re-assert that velocity in your collision function:

rb.velocity = rb.velocity.normalized * DesiredSpeed;

where DesiredSpeed is a float representing how fast you want things to go.

That also lets you increase adjust DesiredSpeed yourself over time, such as to make the game harder if you’re dodging this thing.

NOTE: collision is called AFTER the new “outbound” velocity has been set.

NOTE: with physics you might not always preserve direction because of friction: when it hits the wall, spin is imparted to the ball.

You can reduce this by using friction == 0 physic materials so almost no spin is imparted, but it always seems to drift a bit.

Or if it’s a simple box, do your own physics and reflect it…

You don’t need a script to make it bounce. If you add a physics material with Bounciness set to 1 and ‘Bounce Combine’ set to Maximum then it’ll bounce forever. You’ll just need to give it a push to get it started.

And like Kurt says you should remove friction by setting the Friction values to 0 and ‘Friction Combine’ to Minimum. This will prevent the ball from spinning which could cause it to bounce and deflect unpredictably.

I set the ball to a physics material with the settings you gave, and it is no longer rolling. (Or at least, it’s rare enough I haven’t seen it.)

Actually with a bounce of 1 you will have an object that bounces increasingly higher over time for some reason.

Notable: by setting the linearVelocity you override any physics forces you apply. The AddForce does only come into effect for exactly one FixedUpdate, which only works due to using the Impulse mode. Impulse applies the full force instantly, whereas Force is meant to be applied repeatedly and if you were to use that, the effect is almost certainly negligible.

Ideally you’ll want to replace setting linearVelocity with AddForce and Force mode to account for the object’s mass and to make it “physical” ie since it’s a rolling ball you want to not just push it in a given direction, you want to have it pick up the friction forces as well. This is most likely why your ball isn’t rolling, it’s only sliding because you merely change its velocity.

The reason is floating point precision and a high fixed time step. Simplest solution is to reduce the Bounciness amount to 0.99. Or if the ball is a core feature of their game then they can decrease the ‘Fixed Timestep’ value in the Time settings.

Another simple solution is to monitor the velocity of the ball to make sure it stays within a specified range.

I should also add that the imprecise bounce is only an issue when under the influence of gravity which OP doesn’t seem to be using.