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?

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 :wink:

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.