Hi there,
I just finished the Block breaker part of the course and I am trying to add some power-ups to the game. One of the power-ups, I thought, could be duplicating the ball. My logic is that some of the blocks would yield an object and if you could catch it you will get a random power-up. I created a prefab and a script for the power-up and managed to make the blocks yield this prefab with a rigidbody(so it will slowly come down).
In the script, I created a switch case loop with a randomized index and added methods to the loop so that every time the player catches a power-up, it will have a random effect. I also managed to duplicate the ball and add some velocity and a new layer to it.
Yet whenever that method runs and instantiates the new ball, the lines on the ball.cs(paddleToBallDist or gs.autoPlayOn == true) are giving Null reference exception error.
This is the power-up script
public class PowerUp : MonoBehaviour
{
Paddle paddle;
Ball ball;
[SerializeField]GameObject myBall;
int powerUpArray;
// Start is called before the first frame update
void Start()
{
ball = FindObjectOfType<Ball>();
paddle = FindObjectOfType<Paddle>();
powerUpArray = UnityEngine.Random.Range(1, 5);
}
// Update is called once per frame
void Update()
{
}
private void OnCollisionEnter2D(Collision2D collision)
{
Destroy(gameObject);
ExecuteMethodByIndex();
}
private void ShrinkPaddle()
{
paddle.transform.localScale = new Vector2(0.5f, 1);
}
private void EnlargePaddle()
{
paddle.transform.localScale = new Vector2(1.5f, 1);
}
private void NormalisePaddle()
{
paddle.transform.localScale = new Vector2(1, 1);
}
private void DuplicateBall()
{
GameObject dupBall = Instantiate(myBall, transform.position, transform.rotation);
dupBall.GetComponent<Rigidbody2D>().velocity = new Vector2(8, 2);
dupBall.layer = 12;
}
void ExecuteMethodByIndex()
{
switch (powerUpArray)
{
case 1: EnlargePaddle();
break;
case 2: ShrinkPaddle();
break;
case 3: NormalisePaddle();
break;
case 4: DuplicateBall();
break;
default:
break;
}
}
}
and this is the ball.cs
public class Ball : MonoBehaviour
{
//config params
[SerializeField] Paddle paddle1;
[SerializeField] float velX = 2f, velY = 15f;
[SerializeField] AudioClip[] sounds;
[SerializeField] float randomBounce = 0.1f;
//state
Vector2 paddleToBallDist;
bool hasStarted = false;
//cached references
GameStatus gs;
GameStatus myGameStatus;
AudioSource myAudioSource;
Rigidbody2D myRigidbody2D;
// Start is called before the first frame update
void Start()
{
paddleToBallDist = transform.position - paddle1.transform.position;
myAudioSource = GetComponent<AudioSource>();
myRigidbody2D = GetComponent<Rigidbody2D>();
myGameStatus = GetComponent<GameStatus>();
gs = FindObjectOfType<GameStatus>();
}
// Update is called once per frame
void Update()
{
if (!hasStarted)
{
if (gs.autoPlayOn==true)
{
LockBallToPaddle();
Launch();
}
else
{
LockBallToPaddle();
LaunchOnMouseClick();
}
}
}
private void LaunchOnMouseClick()
{
if(Input.GetMouseButtonDown(0))
{
hasStarted = true;
myRigidbody2D.velocity = new Vector2(velX, velY);
}
}
private void Launch()
{
hasStarted = true;
myRigidbody2D.velocity = new Vector2(velX, velY);
}
private void LockBallToPaddle()
{
Vector2 paddlePos = new Vector2(paddle1.transform.position.x, paddle1.transform.position.y);
transform.position = paddlePos + paddleToBallDist;
}
private void OnCollisionEnter2D(Collision2D collision)
{
Vector2 velocityTweak = new Vector2(UnityEngine.Random.Range(0, randomBounce), UnityEngine.Random.Range(0, randomBounce));
if(hasStarted)
{
AudioClip clip = sounds[UnityEngine.Random.Range(0,sounds.Length)] ;
myAudioSource .PlayOneShot(clip);
myRigidbody2D.velocity += velocityTweak;
}
}
}
I really liked the idea of duplicating the ball so I wanted to fiddle a bit more to solve it before abandoning it and ask you people for help in the meantime…=)
Thanx in advance.Cheers.
edit 1: The error is occurring on the LockBallToPaddle() line which is in the Update()…But I don’t understand why since that method runs inside if(!hasStarted) and the instantiate that I’m trying is when hasStarted==true.