- Home /
DestroyImmediate Prefabs
So I am writing an editor script that will take a prefab and create an instance of it with particular settings. Easy enough. Before I create an instance of it, however, I want to delete any instance of it in the scene with the same name, whether it is an instance of the prefab or just a game object with the same name. Now the problem I am running into is it will easily destroy the game objects with the same name but it will not destroy a game object connected to a prefab, instead it will disconnect the game object from the prefab. If I run the code again it will then destroy the game object since it is not connected to a prefab anymore.
Here is my code:
GameObject oldGO = GameObject.Find(replaceObject.name);
while(oldGO != null && oldGO.name != "")
{
GameObject.DestroyImmediate(oldGO);
oldGO = GameObject.Find(replaceObject.name);
}
newGO = (GameObject)GameObject.Instantiate(replaceObject); // creates a new instance of the object
Step 1- clicked load xml, destorys game objects of name "test" and disconnects game objects of name "test" that are connected to a prefab
Step 2- clicked load xml again, destroys remaining game objects of name "test"
Step 3- now all game objects named test are deleted
Can someone tell me why and how to fix my code so it will destroy the game objects connected to a prefab and not just disconnect them.
UPDATE: 01/05/11
I am not looking for a new solution of how to do what I am doing, I am trying to get an answer of why DestroyImmediate() is not working how it should. So I did more debugging and looked further into my issue and found what the true problem is.
So I am trying to destroy all instances of an object with a particular name, even if they are connected to a prefab, and I will then create a single instance of it with new data that I pull in from an xml. The idea is I never want more than one of this object in the scene at any time. To go about this I go through a loop to search for every game object with the same name and try to destroy it. The problem that I am running into is any game object that is connected to a prefab will, appear, to not get destroyed but rather it will disconnect from the prefab.
When I looked further I found out that it is destroying the instance of the prefab but immediately will create a new instance of the prefab with all of the same data and name but this new instance is not connected to the original prefab. What I want to know is why this is happening? Why is it recreating the object after destroying it? It only happens to game objects that are connected to a prefab.
UPDATE 2: 01/05/11
So I am one step closer into finding out what the problem is. I took artm's function and edited it a bit:
public static void KillObjectsOfName(string name)
{
GameObject victim;
while(victim = GameObject.Find(name))
Object.DestroyImmediate(victim);
}
I use this function in two places, one before loading my xml and once afterward. It fails to function correctly if I load from an xml before or after running this function. However if I run this function alone without loading from an xml it excutes perfectly. Haven't found out why and so that is my next step.
Why do you want to destroy instances of a prefab and immediately instantiate it again? You can change the prefab and have its instances updated automatically.
Because I do not want any of the original instances, I only want one in the scene at all times and I am loading the data for it from an xml.
Answer by femi · Jan 04, 2011 at 06:23 PM
I do not want any of the original instances, I only want one in the scene at all times and I am loading the data for it from an xml
So create one and only update the prefab, don't create new instances. the dangling objects are probably temporaries from previous runs of the script, so the problem is that the script doesn't clean after itself. It should do something like:
// this way links will persist when the mesh is regenerated Object prefab = AssetDatabase.LoadAssetAtPath (prefabPath, typeof(GameObject)); if (!prefab) { prefab = EditorUtility.CreateEmptyPrefab (prefabPath); }
GameObject tmp = new GameObject(name);
// ... set up your object from XML here (in tmp)
// make sure prefab links remain in tact
EditorUtility.ReplacePrefab (tmp, prefab, ReplacePrefabOptions.ReplaceNameBased);
// get rid of the temporary object (otherwise it stays over in scene)
Object.DestroyImmediate (tmp);
This script doesn't leave temporaries after itself, and only the object that you created from the prefab in the scene yourself will remain. Upon next run the original object will be updated by the script to the new version, which is the resultat you want. No?
Update. The problem seems to lie somewhere else. I made the following script:
using UnityEngine;
public class KillByName : MonoBehaviour {
[ContextMenu("Kill by name (GameObject)")] void Kill() { GameObject victim; while(victim = GameObject.Find("GameObject")) Object.DestroyImmediate(victim); } }
It successfully kills all objects and prefabs called "GameObject" in one go (via context menu of an object I attach it to).
That still doesn't fix my original problem. It is not destroying the instances that are already in the scene. What if there are two prefabs instances in the scene? When I create this new instance, I want to delete the old instances and only have the new one I have created.
O$$anonymous$$. But I can't seem to be able to reproduce your problem. See update.
Please look at my update so you can truly understand what I am asking. Thank you for your responses and I hope you can help me.
What is strange is when I use your script it work just fine but when I take your code and insert into the context of $$anonymous$$e it does the same this it always does for me.
I'm glad my script was useful to you. I take it you've solved your problem already?
Answer by Kristen · Jan 05, 2011 at 08:32 PM
So after a long time of debugging and research I can finally answer my question. So the problem was, I was using trying to destroy objects that were connected to a prefab and right afterward use that prefab to create another object. When I use the reference of the prefab after trying to destroy game objects with a reference to the prefab, it canceled the destroy and would re-instantiate the game object I destroyed. I know it sounds strange but that is the easiest way to explain it. So I had to jump through hoops, create a temp object and use that as my reference instead so I could safely delete objects with references to a prefab.
Hopefully this will help others that run into a similar problem and good luck. Here is an expert of my code that fixed my problem:
//Create temp object to use as a reference GameObject rGO = (GameObject)Object.Instantiate(replaceGO, replaceGO.transform.position, replaceGO.transform.localRotation); rGO.name = "temp"; //name it something different just in case
//kill any gameobjects in the scene with the same
//name as the game object I am loading from xml
KillObjectsOfName(newTran.GetName());
//get the name correct for the temp object
rGO.name = newTran.GetName();
//create the object with xml data
CreateObject(rGO, newTran.GetPosition(), newTran.GetRotation(), newTran.GetScale());
//destory temp object
Object.DestroyImmediate(rGO);
Answer by femi · Feb 01, 2011 at 12:23 AM
A different solution: EditorUtility.UnloadUnusedAssets();
. Calling this after DestroyImmediate
that didn't seem to work makes sure the dangling objects are removed from the scene.
I was experiencing kind of the same issue and this does seem to solve all the problems. Weird-weird-weird, it's not like scene objects should be considered as assets... Anyway, thanks for the mojo, artm!
Brilliant! Good thread i had exactly the same issue, trouble clearing Prefabs that were generated with a custom editor... 4 years later ;D
Your answer
Follow this Question
Related Questions
Object.Destroy destroying all prefabs 1 Answer
Mark gameobject field as changed from prefab 2 Answers
Prefab mode doesn't show prefab, still shows old scene. 7 Answers
Destroying the instance of a gameObject on Android vs in Editor 0 Answers
Cant See More Than Two Levels Of Children In The Project Tab 1 Answer