- Home /
Leaking Textures in custom editor
Hi everyone,
I created a custom editor in which I wanted to have alternating colors between elements, just like the console alternates the background color between multiple log entries.
I used
EditorGUILayout.BeginHorizontal()
to enclose each element, since I have multiple GUI components per element. To change the background color of BeginHorizontal, I dynamically created two textures and alternated them in the background color like this
BackgroundTextures = new Texture2D[] { new Texture2D( 1, 1 ), new Texture2D( 1, 1 ) };
BackgroundTextures[ 0 ].SetPixel( 0, 0, new Color( 0.85f, 0.85f, 0.85f ) );
BackgroundTextures[ 0 ].Apply();
BackgroundTextures[ 1 ].SetPixel( 0, 0, new Color( 0.76f, 0.76f, 0.76f ) );
BackgroundTextures[ 1 ].Apply();
for( int i = 0; i < totalElements; ++i )
{
horizontalRow.normal.background = BackgroundTextures[ elementNr % 2 ];
...
}
This works great (as opposed to GUI.color or GUI.backgroundColor which don't change the color of a BeginHorizontal()). My only problem is once I save the scene, I get the following error:
Texture2D has been leaked 2 times. Which is related to the two Texture2D's I create. But I have no idea where I have to free the textures since I am using them all the time in the editor window. As I said, the warning message occurs every time I save the scene. Does anyone know how to fix these leaks?Cleaning up leaked objects in scene since no game object, component or manager is referencing them
Answer by Bunny83 · Jun 23, 2011 at 02:53 AM
Did you set the HideFlags ? Beside that i can't say much about where you've done something wrong since you only showed the creating part.
That did the trick! Thank you. I was not aware you could set the HideFlags for textures as well.
The hideflags are part of UnityEngine.Object. All Unity objects are derived from it.
@Bunny83 can you please elaborate more? what flag should I set to? I guess the DontSave? but doesn't that mean I have to destroy the textures myself? how does that prevent the leaks?
@vexe: Yes and no ;) All unity objects (derived from UnityEngine.Object) are managed by Unity. If you toggle the playmode all scene-objects will be destroyed. Those not marked with DontSave are usually assets or serializable objects. Even your custo$$anonymous$$spector / EditorWindows are recreated and only the serialized values of it will survive.
So if your editor creates a temporary texture you should mark it with DontSave. Generally i would suggest that you create temporary textures / gameobjects / cameras / .. in OnEnable and destroy them in OnDisable.
Creating a new texture each OnGUI or OnInspectorGUI call is certainly not a good idea since the textures create a lot of garbage each (editor)frame and are only destroyed when you switch playmode / load a new scene / restart the editor.
Those object are not truely leaking since they are still searchable with FindObject(s)OfType. Actually in the current version i use (unity 4.0.1) i can't really reproduce this error. It seems Unity no longer outputs the error message.
It was never a "real" problem since Unity will cleans up such objects at playmode change / recompilation / ...
$$anonymous$$eep in $$anonymous$$d Unity is a game-editor / authoring tool, if it really looses control of a loaded resource then Unity wouldn't notice it and it would be a real memory leak. All objects loaded / created inside the editor are always "managed" by Unity. Since all those objects are searchable Unity don't know when a resource is no longer needed.
So you should always destroy your temporary objects when you don't need them anymore. However it might be a better idea to create the textures as real "assets" and save them to the project. That way multiple instances or your editor / editorwindow could share the same textures. See this question for how to load resources for the editor
Answer by jahroy · Jun 23, 2011 at 04:18 AM
Why not destroy the textures as soon as you exit the for loop? It doesn't look like they are needed anymore. Your code is going to re-create them every time that function is called.
It seems to me that it would make more sense to create your textures outside your code and assign them in the inspector. Is there some reason you want to create new textures from scratch every frame?
Personally I would just use two different GUIStyles and alternate each time through the loop:
/* an array of GUI Styles that can be set in the inspector */
var rowStyles : GUIStyle [2];
function OnGUI ()
{
for ( var i = 0; i < totalElements; i ++ ) {
GUI.Label(someRectangle, someLabel, rowStyles[i % 2]);
}
}
Your answer
Follow this Question
Related Questions
Adding textures to my maps? 2 Answers
Are textured/z-clipped gizmos possible? 0 Answers
Unity memory leak when using a drawing tablet? 1 Answer
How can you tell if a texture is NPOT or not, and what its NPOT import settings are 1 Answer
Where is downloaded things from editor script being saved? 0 Answers