2
\$\begingroup\$

I'm trying to create a simple Breakout-style game. In my game, the ball strikes a paddle that moves with the player's mouse. Depending on the position of the strike, the ball changes its direction. This allows the player to aim the ball.

The problem I'm having is that each time I set the position, the ball loses velocity. I've tweaked every Physics2D setting I could find, but I'm not seeing any changes. Here's what my Ball class looks like:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Ball : MonoBehaviour {

  public float initialVelocity;
  public float collisionAngleRange;
  public Paddle paddle;

  private Rigidbody2D body;

  public void Start() {
    body = GetComponent<Rigidbody2D>();
    body.velocity = VectorUtilities.AngleToVector2(135) * initialVelocity;
  }

  // When colliding with the paddle, use the position of the strike to adjust the ball's position.
  public void OnCollisionEnter2D(Collision2D collision) {

    // Ignore the object if it's not the paddle.
    if (!collision.gameObject.CompareTag("Paddle")) { return; }

    // Get the collision coordinates
    Bounds bounds = collision.gameObject.GetComponent<BoxCollider2D>().bounds;
    float left = bounds.min.x;
    float right = bounds.max.x;

    Vector2 contact = collision.contacts[0].point;

    // Interpolate the contact point and determine the angle.
    float interpolation = (contact.x - left) / (right - left);
    float angle = 90 - collisionAngleRange / 2 + collisionAngleRange * (1 - interpolation);

    // Change the direction of the ball without affecting its speed.
    body.velocity = VectorUtilities.AngleToVector2(angle) * body.velocity.magnitude;

    // Log what's happening with the velocity
    Debug.Log(body.velocity.magnitude);
  }
}

The VectorUtilities class looks like this:

using UnityEngine;

// A set of utility methods and extensions for Vector2 and Vector3.
public static class VectorUtilities {

  public static Vector2 AngleToVector2(float degrees) {
    return new Vector2(Mathf.Cos(degrees * Mathf.Deg2Rad), Mathf.Sin(degrees * Mathf.Deg2Rad));
  }
}

Here are my Ball game object's Rigidbody2D and CircleCollider2D settings:

Ball Rigidbody2D and CircleCollider2D settings

The paddle's settings:

Paddle Rigidbody2D and BoxCollider2D settings

The material settings:

BounceMaterial settings

Physics2D settings:

Physics2D settings

I recognize I could solve this problem by multiplying the ball's normal vector by my desired speed, but it's more important to me to understand why this is happening and to fix the underlying problem. Why does the ball lose speed on every collision, and how can I prevent that from happening?

\$\endgroup\$
7
  • \$\begingroup\$ P.S. I'm and experienced developer, but I'm new to Unity and I haven't touched C# in seven years, so if anything looks funky in my code please let me know. \$\endgroup\$ Apr 2, 2017 at 7:09
  • \$\begingroup\$ Seems odd. How much does the ball's speed decrease each collision? Have you tried leaving the ball's material as bouncy but setting the paddle's as rigid? \$\endgroup\$
    – derstander
    Apr 3, 2017 at 3:46
  • \$\begingroup\$ It decreases by quite a bit on each collision. When I ran it just now, the output from my console was: 3.535534, 2.792838, 0.1950009, 0.1201167 and 0.002097883. I'm happy to throw the source code of what I have up on GitHub if you think it would help to poke around in it. \$\endgroup\$ Apr 3, 2017 at 5:32
  • \$\begingroup\$ I forgot to mention I tried removing the bounce material from the Paddle, but it didn't have any effect. One other odd thing: if I comment out the code in the OnCollisionEnter2D method, the ball still loses speed. However, the speed remains constant when it strikes the walls. \$\endgroup\$ Apr 3, 2017 at 5:50
  • \$\begingroup\$ I should be able to take a look at it on GitHub tomorrow (2017-04-04). Still sort of stumped just by looking at it currently, though. \$\endgroup\$
    – derstander
    Apr 4, 2017 at 3:33

1 Answer 1

3
\$\begingroup\$

I finally figured out what was going on here. Because the mass of the Ball and the mass of the Paddle are the same, the Ball was transferring some of its force into the Paddle when it collided with it. However, since the Paddle had its y position and its rotation frozen, I couldn't actually see the effect of the Ball striking it. Turning off those properties allowed me to see the problem.

The solution was to set the body type of the Paddle to Kinematic, which allows it to register collisions without being affected by them.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .