Hiya,
I am sorry if my scripts looks messy I very beginner
Don’t apologise, no need - just keep moving forwards and enjoy what you are doing
Some observations…
-
BrickPc - it has an array of GameObjects called bricks
-
bricks is initialised in the Start()
method by finding all of the BrickPc game objects
-
The bricks array is only in use within the Fireball()
method within PaddlePc class
Consider this…
If you have 200 bricks in your scene, each brick instance will hold and array of 200 bricks…
…we want to be changing that
I personally wouldn’t choose to keep the array maintaining the collection of bricks actually in a class called brick, or in this case, BrickPc, instead I’d probably place it in some form of level manager / game controller class - but, let’s not worry about that just yet, we can refine again and again etc.
What we do need to worry about though is your 200 bricks storing arrays holding 200 bricks!
You may remember that when you added the BreakableCounter
variable you defined it as static. The reason for this was because by doing so it would be a member of the class rather than the instance of the class, it, therefore, exists only once.
Let’s do the same with the bricks array in the BrickPc class, we will also change the type to BrickPc from GameObject (that was my mistake, sorry), change this line;
public GameObject[] bricks;
…to this;
public static BrickPc[] bricks;
We also need to change the Start()
method just slightly, as otherwise, whilst we only have one instance of the array, we will continue to try to initialise it 200 times…
In the Start()
method within the BrickPc class change this line;
bricks = (GameObject)GameObject.FindObjectsOfType<BrickPc>();
…to this;
// check whether we have already initialised our bricks array
if(bricks == null || bricks.Count <=0)
{
bricks = (BrickPc[])GameObject.FindObjectsOfType<BrickPc>();
}
Let’s now turn our attention to PaddlePc. The FireBall()
method iterates through the array of bricks using this line;
foreach(GameObject brick in brick.bricks)
…because we have made the bricks array static, we need to refer to the class not the instance of the class for our iteration. We also need to change the type back from GameObject to BrickPc. Change the above line to this;
foreach(BrickPc brick in BrickPc.bricks)
Note, you need to do this twice as you have the same line again after the yield.
We are getting close now I believe, this is obviously all untested from my end, but there is one more thing I can think of that may cause you a problem.
With the above changes, you get the array of bricks once and maintain it in the class via the static array. When the player plays the game, some of the individual bricks are going to, presumably, get destroyed. When your player uses the FireBall mechanic, we will iterate through the array collection and try to set the isTrigger
property for each of the game object’s BoxCollider2D components.
The problem is, some of those game objects won’t exist anymore.
You could potentially test this before making further changes, but what I would expect is for your to get some form of NullReferenceException error when there is an attempt to change the value for isTrigger
on the destroyed brick.
Arrays are going to be a bit problematic as there isn’t a nice way to remove items from them, what we can use instead are generic Lists. A further problem is going to be how we actually identify which game object we need to remove from the list.
I have an idea…
Firstly, let’s change the brick array to a list in the BrickPc class.
Change the following line;
public static BrickPc[] bricks;
…to;
public static List<BrickPc> bricks; // generic list of type BrickPc
We also need to update the Start()
method again where you retrieve the array of BrickPc game objects, so change;
// check whether we have already initialised our bricks array
if(bricks == null || bricks.Count <=0)
{
bricks = (BrickPc[])GameObject.FindObjectsOfType<BrickPc>();
}
…to;
// check whether we have already initialised our bricks list
if(bricks == null || bricks.Count <= 0)
{
// written long-hand to make it easier to read
BrickPc[] tempBricks = (BrickPc[])GameObject.FindObjectsOfType<BrickPc>(); // gets the BrickPc game objects as an array
bricks = new List<BrickPc>(tempBricks); // initialise our list from an array
}
Now we need to consider what happens when a brick is destroyed, for that, let’s look at the HandleHits()
method in the BrickPc class.
Before we destroy the game object, we want to remove it from our list, add the following line;
// remove current instance of the BrickPc from the list
bricks.Remove(this);
…before the Destroy(gameObject) statement.
A couple of final thoughts…
In the same way that the original game reset the breakableCount
variable before loading the next level, it would be worth clearing the bricks list before loading the next level. Because bricks is static it will retain it’s value throughout it’s lifetime (until you exit the game).
You can clear the list using the following;
bricks.Clear();
If you have any other features which create bricks, or destroy bricks, you will need to factor this in also, the list needs to reflect, accurately, the bricks that are active in the scene.
Lastly, the above is untested, I think it should be ok, but obviously I don’t have the full project to give it a test.
I hope this helps.