Did anyone run into a memory leak like this and found how to fix it? Tested under Unity 5.1.1f1 (Windows 10) Add this to an editor script, place a sprite in the sprite field and see Unity memory usage increase with each frame. My actual problem is a bit more complicated than this and does not even use the scene view to render the UI but a very custom UI rendered in the OnGUI() of an EditorWindow. This was just the easiest way to demonstrate this problem with ObjectField. Code (CSharp): [InitializeOnLoad] public class GlobalStaticTest { private static Sprite test; static GlobalStaticTest() { SceneView.onSceneGUIDelegate += OnSceneGUI; } private static void OnSceneGUI(SceneView sceneView) { Handles.BeginGUI(); GUILayout.BeginArea(new Rect(0, 0, 200, 200)); { test = (Sprite)EditorGUILayout.ObjectField("test", test, typeof(Sprite), false); } GUILayout.EndArea(); Handles.EndGUI(); } } Here is another example. It even happens in a test like this. If the EditorGUILayout.ObjectField() was in the OnInspectorGUI() then it would be fine. Code (CSharp): public class TEST_OBJECT : MonoBehaviour { public Sprite test; } // .... [CustomEditor(typeof(TEST_OBJECT))] public class TEST_OBJECT_Inspector : Editor { public override void OnInspectorGUI() { } protected void OnSceneGUI() { Handles.BeginGUI(); GUILayout.BeginArea(new Rect(0, 0, 200, 200)); { TEST_OBJECT Target = (TEST_OBJECT)target; Target.test = (Sprite)EditorGUILayout.ObjectField("test", Target.test, typeof(Sprite), false); } GUILayout.EndArea(); Handles.EndGUI(); } } Doing it in the normal/ basic way, like this, causes no problems. Code (CSharp): public class TestWindow : EditorWindow { private static Sprite test; [MenuItem("Window/Test")] public static void Show_TestWindow() { EditorWindow.GetWindow<TestWindow>("Test"); } protected void OnGUI() { test = (Sprite)EditorGUILayout.ObjectField("test", test, typeof(Sprite), false); } }
In my actual code (not the samples above) I've tracked it down to a Repaint() being called from OnGUI() I'll probably never have a use for doing an ObjectField() in OnSceneGUI() since it can just as well then be done in an OnGUI() of EditorWindow or the Inspector. So the original question is not really a problem in such a case though I am curious why this memory leak happens.
Seems to be only when Sprite is used. Texture2D does not cause this problem. This cause no memory leak. Code (CSharp): [InitializeOnLoad] public class GlobalStaticTest { private static Texture2D test2; static GlobalStaticTest() { SceneView.onSceneGUIDelegate += OnSceneGUI; } private static void OnSceneGUI(SceneView sceneView) { Handles.BeginGUI(); test2 = (Texture2D)EditorGUI.ObjectField(new Rect(0, 0, 200, 200), test2, typeof(Texture2D), false); Handles.EndGUI(); } } while this does ... Code (CSharp): [InitializeOnLoad] public class GlobalStaticTest { private static Sprite test1; static GlobalStaticTest() { SceneView.onSceneGUIDelegate += OnSceneGUI; } private static void OnSceneGUI(SceneView sceneView) { Handles.BeginGUI(); test1 = (Sprite)EditorGUI.ObjectField(new Rect(0, 0, 200, 200), test1, typeof(Sprite), false); Handles.EndGUI(); } }
Digged around in the editor dll and tracked it down to the call Code (CSharp): EditorGUIUtility.s_ObjectContent.image = AssetPreview.GetMiniThumbnail(obj); GetMiniThumbnail() is in the C++ side of Unity so I can't go any further. I am going to submit this as a bug. Simple test ... Add a texture and things are stable. Add a sprite and see memory usage increase. Code (CSharp): public class TEST_OBJECT : MonoBehaviour { public Sprite test1; public Texture2D test2; } ...... [CustomEditor(typeof(TEST_OBJECT))] public class TEST_OBJECT_Inspector : Editor { public override void OnInspectorGUI() { TEST_OBJECT Target = (TEST_OBJECT)target; Target.test1 = (Sprite)EditorGUILayout.ObjectField("sprite", Target.test1, typeof(Sprite), false); Target.test2 = (Texture2D)EditorGUILayout.ObjectField("texture", Target.test2, typeof(Texture2D), false); } protected void OnSceneGUI() { TEST_OBJECT Target = (TEST_OBJECT)target; Handles.BeginGUI(); GUILayout.BeginArea(new Rect(0, 0, 100, 200)); { if (Event.current.type == EventType.Repaint) { // sprite if (Target.test1 != null) { Texture2D img = AssetPreview.GetMiniThumbnail(Target.test1); GUIContent content = new GUIContent(img); GUIStyle.none.Draw(new Rect(0, 0, 100, 100), content.image, false, false, false, false); } // texture if (Target.test2 != null) { Texture2D img = AssetPreview.GetMiniThumbnail(Target.test2); GUIContent content = new GUIContent(img); GUIStyle.none.Draw(new Rect(0, 100, 100, 100), content.image, false, false, false, false); } } } GUILayout.EndArea(); Handles.EndGUI(); } }