Greetings! Here is my problem:
Im trying to place some prefabs, amount is depended on user’s input. When user change input, I need to delete all the prefabs I placed, and place new prefabs depending on input.
I decided to create dummy Game Object, make all generated prefabs childen of Dummy. When I need to clear scene, I will just delete Dummy, and, as I think, it will take away childrens.
Here is my base code:
n = Convert.ToInt32(nInput.text);
var dummyGameObject = new GameObject(dummyName);
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
for (int z = 0; z < n; z++)
{
Instantiate(brick, new Vector3(i, j, z), Quaternion.identity);
}
I tryed to make things like this:
var objLink = (GameObject)Instantiate(brick, new Vector3(i, j, z), Quaternion.identity);
objLink.transform.SetParent(dummyGameObject.transform);
And then remove like this:
Destroy(GameObject.Find(dummyName));
It doesn’t work. Any ideas? Or maybe if you got better idea for easy removing all the content I generated, feel free to share it, I will be thankful.
// WARNING: non tested code ahead
public GameObject prefab;
List<GameObject> generatedObjects = new List<GameObject>();
var object = Instantiate<GameObject>(prefab);
generatedObjects.Add(object);
foreach(var obj in generatedObject)
{
Destroy(obj);
}
Above snippets should work for your issue. What it does is just place a reference to the generated objects in a list, and you can just loop through them whenever you want to destroy them.
Method like you proposed doesn’t work (am I wrong with something?).
List<GameObject> generatedObjects = new List<GameObject>();
var obj = Instantiate(brick, new Vector3(i, j, z), Quaternion.identity);
generatedObjects.Add(obj); // Gets Invalid Argument here
Destroying a parent object does, in fact, destroy all the children. So your basic approach is correct. It’s hard to guess what’s wrong from just “it doesn’t work” – can you be more specific?
(As for your last code, you have an argument type mismatch, which I blame on your use of var… Be more explicit about what types you think you have, and I think you’ll see the problem. Instantiate almost always needs an “as” clause to coerce the result to a useful type.)
Well, I guess that brick is not of type GameObject. As @JoeStrout said, be more explicit. Though I will suggest using the angled bracket ( ) version of Instantiate like I did in my snippet, as that will remove the need for the ‘as’ clause as well as the need to replace the ‘var’ keyword. Rule of thumb is use for the use of ‘var’ is as follows: “Use var if the intent is clear on the right hand side of the assignment. Use an explicit type if the intent is not clear from the right hand side”. Some examples:
// Here it is clear that I instantiate an object of type GameObject, so I can use var.
var obj = Instantiate<GameObject>(brick);
// Here I have no idea what the type is that I am getting back from Instantiate,
// so I should really be explicit on the left hand side, or be explicit in the cast.
// Also, by default Instantiate returns a UnityEngine.Object, so in 9/10 cases you want to cast
var obj = Instantiate(brick);
// Explicit type sample
UnityEngine.Object obj = Instantiate(brick);
// Explicit casting samples
var obj = (GameObject)Instantiate(brick);
var obj = Instantiate(brick) as GameObject;
That’s a really good point. I normally use the generic (angle-brackets) version of these methods myself; I don’t know why I didn’t think of it this morning. Better in every way!
I still use the generic and then set the position and parent manually.
I tend to find this improves error handling. If you mess up the types the generic will fail at compile time. The non generic will not fail until runtime. And sometimes you may not actually run the code just by hitting play, so failure can take a while.
"this will put the prefab gameobjects into a list and destroy them, sort of like a bin?"
Example code destroys the GameObjects in List ‘generatedObjects’. This code would be used runtime, so GameObjects will simply be removed from your scene.