Resetting the ball to the paddle

I’ve been trying to add life counter, I came up with this code, it resets the ball to the paddle but the ball immediately falls through it causing to quickly lose 3 lifes and load “lose” scene. How do i stop the ball at the paddle? it’s probably easy :stuck_out_tongue:

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

    public class LoseCollider : MonoBehaviour {
    private bool GameStarted = false;
    private LevelManager levelManager;
    public Paddle paddle;
    public Ball ball;
    public Vector3 paddleToBallVector;
    private int lifes=3;
    void Start()
    {
        ball = GameObject.FindObjectOfType<Ball>();
        paddle = GameObject.FindObjectOfType<Paddle>();
        levelManager= GameObject.FindObjectOfType<LevelManager>();
    }
    void Update()
    {
        GameStarted = false;
    }
    void OnTriggerExit2D(Collider2D trigger)
    {
        lifes--;
        if (!GameStarted)
        {
            ball.transform.position = paddleToBallVector + new Vector3(paddle.transform.position.x, 0f, 0f);
        }
        if (Input.GetMouseButtonDown(0) && (GameStarted != false))
        {
            GameStarted = true;
            ball.GetComponent<Rigidbody2D>().velocity = new Vector2(Random.Range(-2f, 2f), 12f);
        }

        print(lifes);
        if (lifes<=0)
        {
            levelManager.LoadLevel("Lose");
            
            lifes = 3;
        }
        
    }

    private void OnCollisionEnter2D(Collision2D collision)
    {
        print("Collision");
    }
    
}

Hi,

When you reset the ball’s position you are currently setting it to 0f on the Y. What is the position of the ball at the beginning of a new game?

The reason I ask is that if you place it in the middle of your paddle you may find that the OnCollisionEnter2D method is not triggered as the one of the colliders is inside another and ignored.


See also;

its y=0,82

So, in this line in your OnTriggerExit2D method;

ball.transform.position = paddleToBallVector + new Vector3(paddle.transform.position.x, 0f, 0f);

Set the Y position to 0.82f and see if that makes a difference. If this is above the paddle it may still fall to the paddle, lets see…

I’ve actually changed the code to, it acts the same as the last one.

private int lifes=3;
void Start()
{
    ball = GameObject.FindObjectOfType<Ball>();
    paddle = GameObject.FindObjectOfType<Paddle>();
    levelManager= GameObject.FindObjectOfType<LevelManager>();
}
void Update()
{
    GameStarted = false;
}
void OnTriggerExit2D(Collider2D trigger)
{
    lifes--;
    print(lifes);
    if (lifes <= 0)
    {
        levelManager.LoadLevel("Lose");

        lifes = 3;
    }
    if (!GameStarted)
      {
       GameStarted = false;
       ball.transform.position = paddleToBallVector + paddle.transform.position;
    }
    if (Input.GetMouseButtonDown(0) && (GameStarted != false))
    {
        GameStarted = true;
        ball.GetComponent<Rigidbody2D>().velocity = new Vector2(Random.Range(-2f, 2f), 12f);
    }

    
    
}

Still the same issue though, as you are not resetting the Y position of the Ball.

Ok I dont get it.

Just as a test, try this in your OnTriggerExit2D method;

    if (!GameStarted)
      {
       GameStarted = false;
       ball.transform.position = new Vector2(paddle.transform.position.x, 0.82f);
    }

The paddleToBallVector is redundant because you don’t set that variable anywhere in the code.

What happens if you use the example I gave you?

Works just the same as the one i’ve just sent you. Sorry for wrong formatting I was slamming tab to get it right and it posted accidentally :smiley:

Ok the ball resets just fine but it doesnt stop, it keeps going instantly.
I believe it happens because it’s not set in the Update() am i wrong?

Ok, so now the position is correct, you need to deal with the velocity. Try something like this;

    /// <summary>
    /// Stops the ball from moving immediately
    /// </summary>
    private void ImmediateStop()
    {
        this.GetComponent<Rigidbody2D>().velocity = new Vector2(0, 0);
    }

Call ImmediateStop when you reset the ball.

O man this looks so funny. The process just slowed down and thats all :smiley: somehow velocity is being inherited i guess.

The ImmediateStop code I posted should be placed in the Ball.cs script.

Can you post the code from your Ball.cs script please.

Sure.

public class Ball : MonoBehaviour
{
public static Ball instance;
public Paddle paddle;
public Vector3 paddleToBallVector;
private bool GameStarted = false;
private Rigidbody2D BallVelocity;

// Use this for initialization
void Start()
{
    paddle = GameObject.FindObjectOfType<Paddle>();
    paddleToBallVector = this.transform.position - paddle.transform.position;
    GameStarted = false;

}


// Update is called once per frame
void Update()
{

    if (!GameStarted)
    {
        this.transform.position =paddleToBallVector + paddle.transform.position;
    }
    if ((Input.GetMouseButtonDown(0)) && (!GameStarted))
    {
        GameStarted = true;
        this.GetComponent<Rigidbody2D>().velocity = new Vector2(Random.Range(-2f, 2f), 12f);
    }
}

void OnCollisionEnter2D(Collision2D collision)
{
    Vector2 tweak = new Vector2(Random.Range(-0.5f, 0.5f), Random.Range(0f, 2f));
    GetComponent<Rigidbody2D>().velocity += tweak;
    if (GameStarted == true)
    {
        GetComponent<AudioSource>().Play();
    }
}
}

You are trying to do quite a lot of non-lose-colliding things within your LoseCollider.cs script.

If I were you I would consider adding some additional functionality to the Ball.cs script. For example, consider adding a Reset method which can both position and interact with the GameStarted variable within Ball. Currently your GameStarted variable in the LoseCollider.cs script is completely separate.

Then, in your LoseCollider.cs script, with the reference to the ball that you have, make a call to Ball.Reset for example when the condition is correct, e.g. OnCollisionEnter2D.

You can then remove the duplicated code from Ball.cs you have added to LoseCollider.cs, leaving it where it makes more sense.

Your Ball.cs script might look something like this;

public class Ball : MonoBehaviour
{
	public static Ball instance;
	public Paddle paddle;
	public Vector3 paddleToBallVector;
	private bool GameStarted = false;
	private Rigidbody2D BallVelocity;

	// Use this for initialization
	void Start()
	{
		paddle = GameObject.FindObjectOfType<Paddle>();
		paddleToBallVector = this.transform.position - paddle.transform.position;
		GameStarted = false;
	}


	// Update is called once per frame
	void Update()
	{
		if (!GameStarted)
		{
			this.transform.position =paddleToBallVector + paddle.transform.position;
		}
		if ((Input.GetMouseButtonDown(0)) && (!GameStarted))
		{
			GameStarted = true;
			this.GetComponent<Rigidbody2D>().velocity = new Vector2(Random.Range(-2f, 2f), 12f);
		}
	}

	void OnCollisionEnter2D(Collision2D collision)
	{
		Vector2 tweak = new Vector2(Random.Range(-0.5f, 0.5f), Random.Range(0f, 2f));
		GetComponent<Rigidbody2D>().velocity += tweak;
		if (GameStarted == true)
		{
			GetComponent<AudioSource>().Play();
		}
	}
	
	public void Reset()
	{
		GameStarted = false;
		
		ImmediateStop();

		this.transform.position = new Vector2(paddle.transform.position.x, 0.82f);
		paddleToBallVector = this.transform.position - paddle.transform.position;
	}

    private void ImmediateStop()
    {
        this.GetComponent<Rigidbody2D>().velocity = new Vector2(0, 0);
    }	
}

and your LoseCollider.cs perhaps like this;

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

public class LoseCollider : MonoBehaviour 
{
	private LevelManager levelManager;
	public Ball ball;
	private int lifes=3;

	void Start()
	{
		ball = GameObject.FindObjectOfType<Ball>();
		levelManager= GameObject.FindObjectOfType<LevelManager>();
	}

	private void OnCollisionEnter2D(Collision2D collision)
	{
		lifes--;
		
		if (lifes<=0)
		{
			levelManager.LoadLevel("Lose");
		}
		else
		{
		    ball.Reset();	
		}
	}

}

I’ve done what u just said but weird things are happening. The is ball now instantly going up very slowly at the start, then I can add velocity by clicking once.

Then after I lose nothing happens, balls falls through not reseting :smiley:

This is ball.cs:

public class Ball : MonoBehaviour
{
public static Ball instance;
public Paddle paddle;
public Vector3 paddleToBallVector;
private bool GameStarted = false;
private Rigidbody2D BallVelocity;

// Use this for initialization
void Start()
{
    GameObject.FindObjectOfType<LoseCollider>();
    paddle = GameObject.FindObjectOfType<Paddle>();
    paddleToBallVector = this.transform.position - paddle.transform.position;
    GameStarted = false;

}


// Update is called once per frame
void Update()
{
    if ((Input.GetMouseButtonDown(0)) && (!GameStarted))
    {
        GameStarted = true;
        this.GetComponent<Rigidbody2D>().velocity = new Vector2(Random.Range(-2f, 2f), 12f);
    }
}

void OnCollisionEnter2D(Collision2D collision)
{
    Vector2 tweak = new Vector2(Random.Range(-0.5f, 0.5f), Random.Range(0f, 2f));
    GetComponent<Rigidbody2D>().velocity += tweak;
    if (GameStarted == true)
    {
        GetComponent<AudioSource>().Play();
    }
}
public void Reset()
{
        GameStarted = false;
        ImmediateStop();
        this.transform.position = new Vector2(paddle.transform.position.x, 0.82f);
        this.transform.position = paddleToBallVector - paddle.transform.position;
}
void ImmediateStop()
{
    this.GetComponent<Rigidbody2D>().velocity = new Vector2(0, 0);
}
}

Could you .zip up your project so I can grab a copy and take a quick look please.

The forum will allow uploads of up to 10mb, if your project is larger than that then you’ll need to use a service like Dropbox or Google Drive and share the URL with me.

You have incorrectly copied the code for the Reset method.

Yea you are right. It resets. But how do I solve this “slowly rising ball” problem? I’d rather have it sitting solid on the paddle rather than slowly bouncing.

If I had to make a guess, without seeing the project, I would suggest that your Y position of 0.82f allows the ball to make contact with the paddle, rather than leaving a small gap. As such, it is probably then triggering your Ball’s OnCollisionEnter2D method, but without seeing the project, this is merely a guess.

If I am correct, increasing the 0.82f to a value that leaves a very slight gap between the ball and the paddle should help.

Alternatively, you could put a check in the OnCollisionEnter2D method to see if the game has started, e.g.

void OnCollisionEnter2D(Collision2D collision)
{
	if(GameStarted)
	{
		Vector2 tweak = new Vector2(Random.Range(-0.5f, 0.5f), Random.Range(0f, 2f));
		GetComponent<Rigidbody2D>().velocity += tweak;
		if (GameStarted == true)
		{
			GetComponent<AudioSource>().Play();
		}
	}
}

Privacy & Terms