[Help] Pong bounce not working properly?

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

public class ball : MonoBehaviour {

   private Rigidbody2D rb;
   private List<Vector2> left_Start;
   private List<Vector2> right_Start;
   private Vector2 ball_Vector;

   private float score_Left;
   private float score_Right;

   private int random;

   public float speed = 1.0f;

   void Start () {
     
     rb = GetComponent<Rigidbody2D> ();

     rb.velocity = new Vector2 (-speed, -speed);

     random = Random.Range (1, 4);

     if (random == 1) {
       rb.velocity = new Vector2 (-speed, speed);
     } else if (random == 2) {
       rb.velocity = new Vector2 (-speed, -speed);
     } else if (random == 3) {
       rb.velocity = new Vector2 (speed, speed);
     } else if (random == 4) {
       rb.velocity = new Vector2 (speed, -speed);
     }
   }
     
   void OnCollisionEnter2D (Collision2D col) {
     
     Vector2 tempVec = rb.velocity;

     if (col.gameObject.tag == "Wall") {
       tempVec.y *= (-1);
       rb.velocity = tempVec;
     } else if (col.gameObject.tag == "paddle_Left" || col.gameObject.tag == "paddle_Right") {
       tempVec.x *= (-1);
       rb.velocity = tempVec;
     }
   }
}

So this is my ball.cs script applied to my ball with the top and bottom walls of the pong arena tagged correctly as “Wall”.

The script works as expected on a ball speed of 1, however if it hits 2 it doesn’t bounce, if it hits 3 it bounces, anything higher than 3 it does not bounce. Using Debug.Log between lines between 23/24 and 38/39 I find that the if the vector is 1 or 3 then it will follow into the function correctly, however if it is any other number then the Y vector drops off entirely and the X is reduced by almost a square root.

I have absolutely no idea what is going wrong, any help would be appreciated.

You need to reflect off of a wall, not simply change the Y value. consider that you hit the corner of a paddle, then your reflection should be a little different.

here is a working example using sprites and rigidbody movement.

using UnityEngine;
using System.Collections;

[RequireComponent (typeof(Rigidbody2D))]
public class test : MonoBehaviour {
    Rigidbody2D rb;
    Vector2 dir;
    public float speed = 1;



    void Start() {
        rb = gameObject.GetComponent<Rigidbody2D>();

        var random = Random.RandomRange(1, 4);
        dir = new Vector2(-1, 1);
        if (random == 2) dir = new Vector2(-1, -1);
        if (random == 3) dir = new Vector2(1, 1);
        if (random == 4) dir = new Vector2(1, -1);

        rb.velocity = dir * speed;
    }

    void Update() {
        speed += Time.deltaTime * 0.05f;
    }

    void OnCollisionEnter2D(Collision2D col)
    {
        foreach (var contact in col.contacts) {
            dir = Vector2.Reflect(dir, contact.normal);
            rb.velocity = dir * speed;
        }
        
    }
}

So taking into account your code, this is my revised script that now no longer bounces at all.

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

public class ball : MonoBehaviour {

	private Rigidbody2D rb;

	private Vector2 dir;

	public float speed = 1.0f;


	private int count = 0;


	void Start () {
		rb = GetComponent<Rigidbody2D> ();

		int random = Random.Range (1, 4);

		dir = new Vector2(0, 0);
		Debug.Log ("LOG # " + (count++) + " :  X Vector == " + (rb.velocity.x) + "\t\tY Vector == " + (rb.velocity.y));
		if (random == 1)
			dir = new Vector2 (-1, 1);
		else if (random == 2)
			dir = new Vector2 (-1, -1);
		else if (random == 3)
			dir = new Vector2 (1, 1);
		else if (random == 4)
			dir = new Vector2 (1, -1);
		Debug.Log ("LOG # " + (count++) + " :  X Vector == " + (rb.velocity.x) + "\t\tY Vector == " + (rb.velocity.y));
		rb.velocity = dir * speed;
		Debug.Log ("LOG # " + (count++) + " :  X Vector == " + (rb.velocity.x) + "\t\tY Vector == " + (rb.velocity.y));
	}
		
	void OnCollisionEnter2D (Collision2D col) {
		Debug.Log ("LOG # " + (count++) + " :  X Vector == " + (rb.velocity.x) + "\t\tY Vector == " + (rb.velocity.y));
		foreach (var contact in col.contacts) {
			dir = Vector2.Reflect (dir, contact.normal);
			Debug.Log ("LOG # " + (count++) + " :  X Vector == " + (rb.velocity.x) + "\t\tY Vector == " + (rb.velocity.y));
			rb.velocity = dir * speed;
			Debug.Log ("LOG # " + (count++) + " :  X Vector == " + (rb.velocity.x) + "\t\tY Vector == " + (rb.velocity.y));
		}
		Debug.Log ("LOG # " + (count++) + " :  X Vector == " + (rb.velocity.x) + "\t\tY Vector == " + (rb.velocity.y));
		/*
		Vector2 tempVec = rb.velocity;

		if (col.gameObject.tag == "Wall") {
			tempVec.y *= (-1);
			rb.velocity = tempVec;
		} else if (col.gameObject.tag == "paddle_Left" || col.gameObject.tag == "paddle_Right") {
			tempVec.x *= (-1);
			rb.velocity = tempVec;
		}*/
	}
}

The Debug.Logs say that the vector changes as expected, but then the ball doesn’t actually change direction, what is going on??

As far as I can tell, it seems to work.

https://www.youtube.com/watch?v=wgc4MopLXyc

Do you have a circle collider on the ball?

I did not, I was using a box collider because my sprite was a square. That did fix it though, why would that even break it?

I can think of two scenarios why the box may not have worked.

In one case, your box collider was not placed on the ball sprite very well. Thus, possibly no true collision of colliders really occurred.

However, there is another difference. The box collider appears to have two points of contact when it hits, whereas the circle collider has one point of contact.

You can print out the number like so in OnCollisionEnter2D:

Debug.Log ("num contacts: " + col.contacts.Length);

As a quick test you can insert a “break” so your loop only uses one point of contact:

        foreach (var contact in col.contacts) {
            dir = Vector2.Reflect (dir, contact.normal);
            Debug.Log ("LOG # " + (count++) + " :  X Vector == " + (rb.velocity.x) + "\t\tY Vector == " + (rb.velocity.y));
            rb.velocity = dir * speed;
            Debug.Log ("LOG # " + (count++) + " :  X Vector == " + (rb.velocity.x) + "\t\tY Vector == " + (rb.velocity.y));
            break;
        }

That way, the loop won’t really loop and will just use the first contact point.