- Home /
Adding MonoBehaviour to HideAndDontSave GameObject makes scene dirty and creates leaks even when component properly destroyed
I want to create hidden game object with script on it, as part of making editor tool. That should not make scene dirty (mark it as it has changes).
Here is test script that creates hidden GameObject, adds script to it, and then destroys script and object.
using UnityEngine;
using UnityEditor;
using System.Collections;
public class MyEditorWindow : EditorWindow
{
[MenuItem("Window/MyEditorWindow")]
static void Init()
{
EditorWindow.GetWindow<MyEditorWindow>(false, "Title");
}
void OnGUI()
{
if(GUILayout.Button("Test Hiden Object+MonoScript Creation"))
Test();
}
void Test()
{
GameObject hiddenGO = new GameObject();
hiddenGO.hideFlags = HideFlags.HideAndDontSave;
HiddenMonoScript hiddenMS = hiddenGO.AddComponent<HiddenMonoScript>();
hiddenMS.hideFlags = HideFlags.HideAndDontSave;
Object.DestroyImmediate(hiddenMS);
Object.DestroyImmediate(hiddenGO);
}
}
And here is MonoBehaviour used for test:
using UnityEngine;
[ExecuteInEditMode]
public class HiddenMonoScript : MonoBehaviour
{}
After every recompilation, first execution of Test (click on button in MyEditorWindow) makes scene dirty and when saving it I get a message in console: Cleaning up leaked objects in scene since no game object, component or manager is referencing them MonoScript has been leaked 1 times.
Subsequent Test executions do not mark scene dirty and do not increase number of leaks. Until next compilation occurs and first Test after compilation is executed.
Am I doing something wrong or is it a bug?
Answer by Bunny83 · May 27, 2011 at 11:20 AM
I guess the problem is that you use ExecuteInEditMode and in addition you destroy it in the same run. ExecuteInEditMode will register the MonoBehaviour to get Start and Update called. You should wait for at least one frame before removing the object. You don't need to destroy the MonoBehaviour because it should be removed when the GO is destroyed.
Since you can't use coroutines in the Editor (except you use your own handler), the best way for ExecuteInEditMode scripts is that you destroy the gameobject in the Start() function of your script. Start is executed at the beginning of the next editor-frame.
If the GameObject exists only for one frame the hideflags are almost useless ;)
edit(copied from comments)
If i run your code above i don't get any warning/error. The scene doesn't get dirty. I put a Debug.Log into the Awake function of the "HiddenMonoScript" and it prints out everytime i click the button.
The error/warning says "MonoScript". That would actually refer to the Textasset and not the MonoBehaviour class that is generated from the MonoScript. Where is your HiddenMonoScript located?
As far as i know namespaces are not that bad, but every class that should be able to get attached to a GameObject needs to be in a seperate file. MonoBehaviours are always associated with their corresponding scripts. A base-class that is derived from MonoBehaviour and that isn't attached directly to a GameObject can be placed wherever you like. Only concrete classes need their own file(classname==filename).
There should be no difference between in-editor attaching (via drag&drop) or using AddComponent from a script.
The problem was noticed in more complex scenario, where I don't destroy game object or $$anonymous$$onoBehaviour in same frame, so I don't think that's an issue. This test is just for demonstration purpose. I'm aware of not needing to destroy $$anonymous$$onoBehavior before GameObject, but it was more explicit way and I wanted to remove any suspicion that it is destroyed. Also, it does not explain why first Test run makes scene dirty and subsequent ones do not (same for the leak).
If i run your code above i don't get any warning/error. The scene doesn't get dirty. I put a Debug.Log into the Awake function of the "Hidden$$anonymous$$onoScript" and it prints out everytime i click the button.
The error/warning says "$$anonymous$$onoScript". That would actually refer to the Textasset and not the $$anonymous$$onoBehaviour class that is generated from the $$anonymous$$onoScript. Where is your Hidden$$anonymous$$onoScript located?
Very good! In example I gave in question, location of script really was a problem. I put Hidden$$anonymous$$onoScript in Editor folder with $$anonymous$$yEditorWindow and somehow Unity didn't report a problem when calling AddComponent... it usually does that when something like this happens.
In my complex scenario problem was something else, but your hint led me to right path to answer :) Problem was I put $$anonymous$$onoBehaviour in namespace. I knew that Unity does not support that, but I thought that "not supporting" part was only about manually adding script to GameObject in editor. Didn't have a clue that in adding by script it could produce something like this... Thanks a lot Bunny83.
Can you make your comment an answer or should I accept your first post?
I've added my comment to the answer ;)
It's strange that Unity doesn't complains that your class is an editor script and can't be attached. $$anonymous$$y Unity(3.0) throws an error like that if you try to attach a $$anonymous$$onoBehaviour that is located in an editor folder.
I use Unity v3.3. I made a test now, if I open a project with Hidden$$anonymous$$onoBehaviour already in Editor folder, Test works (with dirty/leak problem). If then I remove script from Editor folder and put it back to Editor folder, running Test reports error in AddComponent.
About namespaces, I put Hidden$$anonymous$$onoBehaviour in namespace $$anonymous$$yNamespace (also add "using $$anonymous$$yNamespace;" to $$anonymous$$yEditorWindow) and Test runs with dirty/leak problem. I tried na$$anonymous$$g script "Hidden$$anonymous$$onoBehaviour.cs" and "$$anonymous$$yNamespace.Hidden$$anonymous$$onoBehaviour.cs" - with same result.
Your answer
Follow this Question
Related Questions
Can't use Script Execution Order 1 Answer
How to prevent Update from *not* being called 2 Answers
My dialogue system has a strange bug 0 Answers
Unity Android Screen Glitch 1 Answer
Getting into Monobehavior 1 Answer