0
\$\begingroup\$

I've been trying so hard to complete a working game of pong for the last couple of weeks but, simply put, the physics of trying to get the ball to bounce correctly of the paddle is preventing me from having a working game. What I would like to do is get the ball to hit the paddle, then bounce off correctly depending on the point of collision with respect to the paddles position:

  • If it hits the top or bottom of the paddle, I would like it to just reflect the y velocity.
  • If it hits the front of the paddle, calculate the normalised position and then redirect it based on this.

The main problem I'm having is, the point of collision isn't exact and always changes, even if I used FixedUpdate() for physics based calculations. There's always a point around the corner that gives the ball a very small and unexpected velocity. Sometimes it even hits the paddle (when the ball is going in the same direction as the paddle) and just travels straight upwards once it hits the paddle. I've tried OnCollisionEnter2D and OnTriggerEnter2D and haven't achieved the expected behaviour.

If anyone could help me to understand what I should do in this situation. That would be incredible as I don't really have anyone to turn to..

Thanks again!

(I thought my code wouldn't really be that beneficial but I have added it anyways, it's what I have right now, the paddle, ball and walls all have colliders and the paddles and ball have rigidbodies, if that helps.)

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

public class BallMovement : MonoBehaviour {

private float speed = 5f;
private float hitCount = 1f;
public static int playerCount = 0;
public static int computerCount = 0;
private static Rigidbody2D ballRigidbody;
private Vector2 theBallVelocity;
private string whichPaddle;

void Start () {
    ballRigidbody = GetComponent<Rigidbody2D> ();
    ballRigidbody.velocity = Vector2.left * speed;
    whichPaddle = "";
}

void FixedUpdate() {
    theBallVelocity = ballRigidbody.velocity;

}

void OnCollisionEnter2D(Collision2D collision) {

    //Calculates the position of the ball on collision and reflects with an angle and velocity relative to the position it collided at.
    if (collision.gameObject.tag == "Player") {

        Vector2 thePosition = ballRigidbody.position;
        float proportionPosition = CalculatePosition (thePosition, collision.transform.position, collision.collider.bounds.size.y);
        float theDifference = 0.0f;

        if (whichPaddle != "Player" && (proportionPosition > 0.52f || proportionPosition < -0.52f)) {
            ballRigidbody.velocity = new Vector2 (theBallVelocity.x, theBallVelocity.y * -1f);
            print ("it's hitting the edge" + proportionPosition);
        }

        if (proportionPosition <= 0.52f && proportionPosition >= -0.52f)  {
            Vector2 direction = new Vector2 (1, proportionPosition).normalized;
            ballRigidbody.velocity = direction * speed * (1f + 0.05f * hitCount);
            hitCount += 1;
            print ("it's not hitting the edge");
        }

        whichPaddle = "Player";
    }

    //Calculates the position of the ball on collision and reflects with an angle and velocity relative to the position it collided at.
    if (collision.gameObject.tag == "Computer") {

        Vector2 thePosition = collision.transform.position;
        float proportionPosition = CalculatePosition (transform.position, collision.transform.position, collision.collider.bounds.size.y);
        float theDifference = 0.0f;

        if (whichPaddle != "Computer" && (proportionPosition > 0.52f || proportionPosition < -0.52f)) {
            ballRigidbody.velocity = new Vector2 (theBallVelocity.x, theBallVelocity.y * -1f);
            print ("it's hitting the edge" + proportionPosition);
        }

        if (proportionPosition <= 0.52f && proportionPosition >= -0.52f) {
            Vector2 direction = new Vector2 (-1, proportionPosition).normalized;
            ballRigidbody.velocity = direction * speed * (1f + 0.05f * hitCount);
            hitCount += 1;
            print ("it's not hitting the edge");
        }

        whichPaddle = "Computer";
    }

    //Reflect the ball when it hits this boundary.
    if (collision.collider.name == "TopBoundary") {
        ballRigidbody.velocity = new Vector2 (theBallVelocity.x, theBallVelocity.y * -1f);
    }

    //Reflect the ball when it hits this boundary.
    if (collision.collider.name == "BottomBoundary") {
        ballRigidbody.velocity = new Vector2 (theBallVelocity.x, theBallVelocity.y * -1f);
    }

    //Essentially resetting everytime a player scores until they only need one more goal.
    if (collision.collider.name == "LeftBoundary") {
        if (computerCount == 8) {
            Reset (ballRigidbody);
        } else {
            ballRigidbody.position = new Vector3 (0, 0, 0);
            ballRigidbody.velocity = Vector2.left * speed;
        }
        hitCount = 1f;
        computerCount += 1;
    }

    //Essentially resetting everytime a player scores until they only need one more goal.
    if (collision.collider.name == "RightBoundary") {
        if (playerCount == 8) {
            Reset (ballRigidbody);
        } else {
            ballRigidbody.position = new Vector3 (0, 0, 0);
            ballRigidbody.velocity = Vector2.left * speed;
        }
        hitCount = 1f;
        playerCount += 1;
    }
}

//Calculate the percentage point at where th ball hits the paddle.
float CalculatePosition(Vector2 ballPosition, Vector2 paddlePosition, float paddleHeight) {
    float y = (ballPosition.y - paddlePosition.y) / paddleHeight;
    return y;
}

//Reset the balls position.
void Reset(Rigidbody2D ball) {
    ball.position = new Vector3 (0, 0, 0);
    ball.velocity = new Vector2 (0, 0);
}
}
\$\endgroup\$
  • \$\begingroup\$ If the default discrete collision detection isn't giving your the fidelity you need, have you tried using continuous collision detection or circle casting? \$\endgroup\$ – DMGregory Mar 28 '18 at 18:24
  • \$\begingroup\$ Oh, I haven't no. I took away the material I had that was causing the unnecessary extra change in direction and thought I could continue down this path but I failed :P I will definitely try this tomorrow and look up tutorials on how to implement it. I thought OnCollisionEnter2D would provide me with the exact coordinates of collision and it doesn't, meaning they're never precise enough to cover the scenarios. With continuous collision detection, will it help me to achieve this? \$\endgroup\$ – Bowcox Mar 28 '18 at 18:39

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.