EditorWindow and new Texture2D

I’m attempting to create a 1x1 texture for use in an EditorWindow. For some reason the Texture2D is being destroyed.

My code currently looks like this:

public class Blah : EditorWindow {
    private Texture2D RED;

    void OnEnable() {
        RED = Make1x1Texture(Color.red);
        Debug.Log("Created RED: " + RED);
    }

    void OnDisable() { ... Debug.Log(), immediate-destroy it ... }

    private static Texture2D Make1x1Texture(Color color) {
        Texture2D result = new Texture2D(1, 1);
        ... set pixels, apply, return ...
    }

    void OnGUI() {
        Debug.Log("OnGUI RED=" + RED);
        ...use...
    }
}

Pretty straightforward. But in the editor console, I see:

Created RED:  (UnityEngine.Texture2D)
OnGUI RED=null

Note RED is not a null reference; rather, it’s a valid reference to a Texture2D that has been destroyed, so the Texture2D ToString() method prints “null” (which sent me in the wrong direction for several minutes).

For some reason, Unity is destroying the Texture2D between the time it’s created and when it’s first used in OnGUI. This results in messages like null texture passed to GUI.DrawTexture when I try to draw it.

At first I was creating the Texture2D with a field initializer, and I thought the scene GC was eating the texture, but now I’m creating it in OnEnable(). I’ve also tried creating it in Awake(). I’ve tried making the field public in case the serializer needs to do something with it. None of these have helped.

The strange part is, sometimes it works, and will continue to work for a while. Then, when I start Unity the next day, it starts failing again. I’m clearly doing something the editor doesn’t like, and either racing or getting into a situation where my code and something in the editor (like the serialization system) are fighting each other and everybody loses.

I can work around the problem by creating and destroying the Texture2D in OnGUI(), but that seems like a waste. And this seems like the sort of problem that could bite me again in the future, so I’d like to understand what’s going on. What is the correct way to do this?

Using Unity 5.1.3f1 Personal.

The problem here is most likely that you create the texture at edit time. Things usually “live” in the game scene. When playmode is changed everything in the scene is destroyed and recreated from serialized data. A Texture can only survive that process when it’s actually serialized as asset in your project.

However since it’s a temporary texture that is only used inside the editor you simply need to set the textures hideFlags to HideFlags.DontSave. This will actually prevent the texture from being destroyed when a new scene is loaded. Things with DontSave actually don’t belong to the scene. Editor stuff should always be marked with DontSave unless you actually save those things as asset to your project. Unity does the same for the sceneView lights, camera, … which are also just gameobjects in the scene but marked as HideAndDontSave.

In addition you might want to use a property like this:

private Texture2D m_RED;
private Texture2D RED
{
    get
    {
        if (m_RED == null)
        {
            m_RED = Make1x1Texture(Color.red);
        }
        return m_RED;
    }
}

That way you can simply use the property all the time. If, for some reason, the texture is destroyed it will be recreated when you access the property.