# Physics2D - prevent ball speed increase when hitting moving objects

Hi,

I am making a brick breaker game and one thing I am finding is that if my ball collides with a moving brick it will massively increase it’s speed, this also happens on occassion without a moving brick, but the moving brick seems to always do this.

I’d like to control the speed of the ball myself, and ideally have the speed remain constant otherwise.

I’ve tried messing with ConstantFoce2D but that seemed to cause other unexpected changes, and it didn’t seem to help as I still got a ball increase in speed.

Here is my code for adding force to the ball at the start:

``````        if (Input.GetKeyUp(KeyCode.Space) && gameStarted == false)
{
gameStarted = true;

transform.SetParent(null);

rb.isKinematic = false;

}
``````

This is how my paddle currently affects the ball:

``````private void OnCollisionEnter2D(Collision2D col)
{
if (col.transform.tag == "Ball")
{

Rigidbody2D colrb = col.rigidbody;
Vector2 ballPosition = col.transform.position;

Vector2 delta = ballPosition - paddlePosition;

Vector2 direction = delta.normalized;

colrb.velocity = direction * speed;
}
``````

Beyond that, collision with the blocks is just handled by Physics 2D.

Is there some way I can maintain things as they are and simply tell my ball object not to increase it’s speed on collisions with moving objects, or ideally, any object (unless I tell it to in a script)?

Thanks.

Get the collision normal and then calculate the correct velocity for it and set it to rigidbody’s .velocity directly. There are other ways but this is sufficient for all and any breakout scenarios.

Use Vector3.Reflect to help.

The problem is this still won’t give you controllable physics. The original breakout and arkabnoid games and possibly pong, would increase angle of reflection based on how close to the edge of the brick the ball hit.

So that’s entirely unrealistic physics. Physx in Unity is for similations. That’s it’s original purpose so given the settings it’ll give a pretty realistic result, just not the one you want, for the mass and velocty.

In Unity you would want to roll your own simple collisions or simply change Physx or Box2D results (Unity’s 3D or 2D physics engines).

Thanks for your reply, I am actually increasing the angle of reflection (and setting direction) based on where on the paddle the ball makes contact, that is what I am going for, and it works reasonably well, but still needs some work.

Here is how I am currently doing it (from the paddle):

``````private void OnCollisionEnter2D(Collision2D col)
{
if (col.transform.tag == "Ball")
{

Rigidbody2D colrb = col.rigidbody;
Vector2 ballPosition = col.transform.position;

Vector2 delta = ballPosition - paddlePosition;

Vector2 direction = delta.normalized;

colrb.velocity = direction * speed;
}
``````

I’m sure there are better ways and I will probably come back to it to give me more control. I also didn’t like the way I was getting some very acute angles sometimes causing a long slow climb up the level so I added this, again not the best way to do things I’m sure, but it’s helped with the issue. Not sure if it’s going to be a hinderance to the player or a neat gameplay feature though.

``````if ((rb.velocity.y < min_y_velocity)&&(Mathf.Sign(rb.velocity.y) == 1))
{
}
else if ((rb.velocity.y > -min_y_velocity) && (Mathf.Sign(rb.velocity.y) == -1))
{
}
``````

In order to keep a constant velocity I have used `rb.velocity = constantSpeed * (rb.velocity.normalized);`

That seems to have done the trick.

I’m also trying to have my ball hit a buoyancy Effector 2D when it hits the floor but I’m having some trouble with this, OnTrigger2D is working Ok, the correct sound is played etc, but the ball seems completely uneffected by the effector.

I placed a test object in the scene with some gravity and it fell onto the effector and buoyancy worked, but with my ball this doesn’t happen, I’m not sure if that is because of the force being applied to the ball?

I tried adding a condition to the code managing my velocity at a constantSpeed:

``````       if (!ballDeath)
{
rb.velocity = constantSpeed * (rb.velocity.normalized);
}
``````

and I set up OnTrigger2D like this:

``````    private void OnTriggerEnter2D(Collider2D col)
{
if (col.gameObject.tag == "Floor")
{
ballDeath = true;
playhitFloorSound();
constantSpeed = 0f;
ballForce = 0f;
Debug.Log("Hit the floor");
}
``````

Just to hard and fast test what was happening, surely the ball should stop dead? Ideally I just want to slow it down a lot but this effector seems to have no effect on my ball, if you can see what I’m doing wrong please let me know.

The ball has a single point of friction so it only takes the slightest gravity application to get it moving again. It sounds to me you’d be best off just not having it collide.

For example:

I don’t use effectors and I’ve moved to using 3D physics so I can’t really help much more. Perhaps someone else can suggest?

Thanks for this I’ll check it out!

So, I just did a test and duplicated my ball object and removed it’s scripts and still had the problem with it not responding to the effector, however when I swapped out it’s circle collider for a box collider it worked.

Is this just a limitation of this 2D effector, anyone know?

Thanks.