- Home /
Unity 5: Clean way to manage dynamically created GameObjects
In Unity 5, what is "clean" way to manage dynamically created game objects?
I've written a component (`MonoBehavior`) that creates/destroys several GameObjects
. The objects are loaded as part of custom customization system that selects portions of character - hair/clothes, etc. Meaning they're visible to player, visible in editor, but are not supposed to be editable in editor. The objects being loaded are meshes with skeletons.
The script behaves in this fashion:
Loads GameObjects from Resources (exact object is determined in script, they are not prefabs)
Attaches them to some portion of the scene (not necessarily to its own node)
Deletes when destroyed.
Deletion:
protected void unloadLastResource(){
if (lastResourceInstance){
if (Application.isEditor){
GameObject.DestroyImmediate(lastResourceInstance);
}
else
GameObject.Destroy(lastResourceInstance);
Resources.UnloadUnusedAssets();
lastResourceInstance = null;
}
}
Creation:
GameObject target = getEffectiveTargetNode();
Object resource = Resources.Load(newResourceName);
instance = Instantiate(resource) as GameObject;
instance.hideFlags = HideFlags.HideAndDontSave;
instance.transform.parent = target.transform;
instance.transform.localPosition = Vector3.zero;
instance.transform.localRotation = Quaternion.identity;
instance.transform.localScale = Vector3.one;
Destruction handler:
void OnDestroy(){
unloadLastResource();
}
That seems to work fine in editor, but when I switch from gaming mode back to edito mode, I get a lot of warnings:
Destroying object multiple times. Don't use DestroyImmediate on the same object in OnDisable or OnDestroy.
UnityEngine.Object:DestroyImmediate(Object)
And I get bunch of new object trees (the ones that are supposed to be deleted - trees originate from object that was loaded along with original "resources" and was attached) at the top level of scene hieararchy.
So, how do I cleanly handle dynamically created gameobjects?
I need to know which flags I need to set, and which steps I should do to ensure that object does not "leak" into scene and is properly destroyed when I delete component that created it.
Advice?
As the warnings suggests, you are doing DestroyImmediate inside OnDestroy...
Don't do that.
I don't understand why you are using DestroyImmediate anyway... if this is a runtime script and not editor script there is no reason to use DestroyImmediate.
@dorpeleg: The script controls customization of a character. Selected parts are visible in editor. Without DestroyImmediate they don't get properly cleaned up in editor. Editor script is derived from this class. Also, warning suggest not to use those methods on the same object
Not very familiar with this question's topic, but regarding dorpeleg's comment and your response: Perhaps you could use the .isPlaying function to decide weather to call destroy or destroyimmidiate
Answer by neginfinity · Mar 31, 2015 at 03:17 PM
I've figured it out.
The problem is caused by this line:
instance.hideFlags = HideFlags.HideAndDontSave;
In hierarchy, this flag affects only ONE object and does not affect object's children. As a result, if you set this flag for the root object in hierarchy and scene gets saved, root will be destroyed, but its children will get serialized (meaning they'll appear in inspector upon scene reload) AND you'll get tons of warnings about destroying same object many times.
To deal with the problem, it is necessary to walk through the entire hierarchy and set the flag to all objects in hierarchy. Which fixes the problem and eliminates all errors.
void makeHierarchyHidden(GameObject obj){
obj.gameObject.hideFlags = HideFlags.HideAndDontSave;
foreach(Transform child in obj.transform){
makeHierarchyHidden(child.gameObject);
}
}
.....
makeHierarchyHidden (newObject);
.....
It is unclear if this only happens when loading non-prefabs from disk, or just in general case with all hierarchical objects.