I've got these two codes that do the same thing in theory but in practice behave very differently and I would like to know why/how to fix it.
void BlockPlacer(){ //Places breakable objects
BlockType BlockKind = BlockType.Hard;
GameObject Block = ReturnBlock (BlockKind);
while(true){
for(int j = 1; j < 4; j++){
for(float i = -width; i < width; i++){
GameObject created = Instantiate (Block, new Vector3 (i, height - j, 10), Quaternion.Euler (0, 0, 0));
print (created.transform.position);
}
}
break;
}
}
as you can see I'm instantiateing an GameObject that is created outside my two for loops and that works as you might expect, on the other example
void BlockPlacer(){ //Places breakable objects
BlockType BlockKind = BlockType.Hard;
while(true){
for(int j = 1; j < 4; j++){
for(float i = -width; i < width; i++){
GameObject created = Instantiate (ReturnBlock (BlockKind), new Vector3 (i, height - j, 10), Quaternion.Euler (0, 0, 0));
print (created.transform.position);
}
}
break;
}
}
I'm doing the same thing but this time I'm geting my GameObject within loops and the program only instantiates once(I've checked my code and everything is being called and returned the way I wanted it, only instantiate doesn't behave as it should)
My theory from testing is that the GameObject is being created at every pass of the loop, but it get's deleted an created again on the next pass, this isn't probably true, but for now, I don't have anything better. All GameObjects are being created from the same Prefab so there might be some inheritance issues. Here is the code that return my GameObject
GameObject ReturnBlock(BlockType Type){
if (Type == BlockType.Soft) {
GameObject SoftBlock = Resources.Load("GameBorderPrefab") as GameObject;
SoftBlock.name = "SoftBlock";
SoftBlock.tag = "Soft"; //Sets a tag for that gameobject
SoftBlock.AddComponent<HitCounter>();
string TextureName = "";
for (int i = 0; i < GameManager.Bricks.Count; i++) {
if (GameManager.Bricks [i].ID == "Soft") {
TextureName = GameManager.Bricks [i].TextureName;
SoftBlock.GetComponent<HitCounter> ().HP = System.Int32.Parse(GameManager.Bricks [i].HitPoints);
}
}
SoftBlock.GetComponent<Renderer> ().material = Resources.Load (TextureName) as Material;
return SoftBlock;
}if (Type == BlockType.Medium) {
GameObject MediumBlock = Resources.Load("GameBorderPrefab") as GameObject;
MediumBlock.name = "MediumBlock";
MediumBlock.tag = "Medium";
MediumBlock.AddComponent<HitCounter>();
string TextureName = "";
for (int i = 0; i < GameManager.Bricks.Count; i++) {
if (GameManager.Bricks [i].ID == "Medium") {
TextureName = GameManager.Bricks [i].TextureName;
MediumBlock.GetComponent<HitCounter> ().HP = System.Int32.Parse(GameManager.Bricks [i].HitPoints);
}
}
MediumBlock.GetComponent<Renderer> ().material = Resources.Load (TextureName) as Material;
return MediumBlock;
}else{//if (Type == BlockType.Hard) {
GameObject HardBlock = Resources.Load ("GameBorderPrefab") as GameObject;
HardBlock.name = "HardBlock";
HardBlock.tag = "Hard";
HardBlock.AddComponent<HitCounter> ();
string TextureName = "";
for (int i = 0; i < GameManager.Bricks.Count; i++) {
if (GameManager.Bricks [i].ID == "Hard") {
TextureName = GameManager.Bricks [i].TextureName;
HardBlock.GetComponent<HitCounter> ().HP = System.Int32.Parse (GameManager.Bricks [i].HitPoints);
}
}
HardBlock.GetComponent<Renderer> ().material = Resources.Load (TextureName) as Material;
return HardBlock;
}
}
Upon further testing, I've writen this code that behaves just like the first code I presented hoping I would see three diferent lines of object being created. Only the first Instantiate worked as expected, others didn't do anything, but all my print functions worked as you would expect
BlockType BlockKind = BlockType.Hard;
GameObject Block = ReturnBlock (BlockKind);
int j = 1;
for(float i = -width; i < width; i++){
GameObject created = Instantiate (Block, new Vector3 (i, height - j, 10), Quaternion.Euler (0, 0, 0));
print (created.transform.position);
}
j = 2;
BlockKind = BlockType.Soft;
Block = ReturnBlock (BlockKind);
for(float i = -width; i < width; i++){
GameObject created = Instantiate (Block, new Vector3 (i, height - j, 10), Quaternion.Euler (0, 0, 0));
print (created.transform.position);
}
j = 3;
BlockKind = BlockType.Medium;
Block = ReturnBlock (BlockKind);
for(float i = -width; i < width; i++){
GameObject created = Instantiate (Block, new Vector3 (i, height - j, 10), Quaternion.Euler (0, 0, 0));
print (created.transform.position);
}
The solution lies in the fact that Unity can't separate what is being instantiated and what is being kept as an empty prefab in Resources folder, that is why the instantiate function would bug out on the second call of ReturnBlock() function. I fixed my bugs by creating a new prefab from scratch for every single one of my block types, is it optimised no, is it a good practice no, but for now it get's the job done.
TL;DR Don't use one prefab to instantiate more than one object, otherwise inheritance will kick in and you will be in trouble.