Search Unity

EditorWindow: Texture2D seem to disappear from a private List

Discussion in 'Editor & General Support' started by joscht, Oct 18, 2018.

  1. joscht

    joscht

    Joined:
    Mar 23, 2017
    Posts:
    4
    Hi everyone
    I'm working on a small editor tool for myself to make placing prefabs in our game easier. Basically I'm showing a small image of every prefab in a window and when selecting it I instantiate it and add it to the scene.

    To display all the prefabs I load all the Textures of the Prefabs (AssetPreview.GetAssetPreview()). I only want to load them once because that operation is rather expensive (I guess?), so I'm storing all these textures in a private List in the EditorWindow.
    While adding the textures to this list (about 52), the first entries of the list are suddenly null. In the end I have 12 null values and 40 textures in the list.
    I really can't explain to myself how this is happening. I'm suspecting either Garbage Collection or that I'm missusing the EditorWindow / lifecycle.

    The code looks like this (I removed some unrelated lines):

    Code (CSharp):
    1.  
    2. public class LevelEditorWindow : EditorWindow {
    3.    private List<Texture2D> textures = new List<Texture2D>();
    4.    // [...]
    5.  
    6.  
    7.     [MenuItem ("Window/Level Editor")]
    8.     static void Init () {
    9.         LevelEditorWindow window = (LevelEditorWindow)EditorWindow.GetWindow (typeof (LevelEditorWindow));
    10.         window.Show();
    11.     }
    12.  
    13.    void OnEnable() {
    14.       LoadAllPrefabs();
    15.       // [...]
    16.    }
    17.  
    18.    private void LoadAllPrefabs() {
    19.       textures.Clear();
    20.      
    21.       string[] allAssets = AssetDatabase.GetAllAssetPaths();
    22.       Array.Sort(allAssets, (x,y) => String.Compare(x, y)); // just to make it appear alphabetically
    23.  
    24.       foreach (string assetPath in allAssets) {
    25.          if (assetPath.EndsWith(".prefab")) {
    26.             // load the prefab object
    27.             GameObject prefab = AssetDatabase.LoadAssetAtPath<GameObject>(assetPath) as GameObject;
    28.            
    29.             // and the preview texture of it
    30.             Texture2D texture = AssetPreview.GetAssetPreview(prefab);
    31.             if (texture != null) { // some might be null (I guess when they have no sprite renderer), not adding those
    32.                textures.Add(texture);
    33.                Debug.Log("First texture after adding " + textures[0]);
    34.             }
    35.  
    36.          }
    37.       }
    38.    }
    While adding the textures, the first ten "disappear" and are suddenly null. To check this I added the Debug.Log. The output looks like this:

    First texture after adding (UnityEngine.Texture2D)
    UnityEngine.Debug:Log(Object)
    LevelEditorWindow:LoadAllPrefabs() (at Assets/Editor/LevelEditorWindow.cs:62)
    LevelEditorWindow:OnEnable() (at Assets/Editor/LevelEditorWindow.cs:290)
    UnityEditor.EditorWindow:GetWindow(Type)
    LevelEditorWindow:Init() (at Assets/Editor/LevelEditorWindow.cs:37)

    [...] Some more which are added, after the first 40 textures are added the texture at index 0 is null
    First texture after adding null
    UnityEngine.Debug:Log(Object)
    LevelEditorWindow:LoadAllPrefabs() (at Assets/Editor/LevelEditorWindow.cs:62)
    LevelEditorWindow:OnEnable() (at Assets/Editor/LevelEditorWindow.cs:290)
    UnityEditor.EditorWindow:GetWindow(Type)
    LevelEditorWindow:Init() (at Assets/Editor/LevelEditorWindow.cs:37)

    I'm always logging the texture at index 0, so I don't understand how this can suddenly be null without me overriding it.
    I checked all the code which accesses the List of textures. Except for the method LoadAllPrefabs, all the access is readonly. The only other access is in OnGUI to display the textures with a foreach (Texture2D texture in textures) and a call to EditorGUI.DrawPreviewTexture(rect, texture);

    I have no idea what is happening. I also tried with keeping the List static. Any ideas on this?
    It's rather hard to find tutorials on more advanced EditorWindow coding, so I'm also happy about suggestions on how to improve it in general.
     
  2. joscht

    joscht

    Joined:
    Mar 23, 2017
    Posts:
    4
    Found the problem, apparently the AssetPreview class has a cache size. When increasing it to e.g. 70, all my textures stay.
    I still don't understand how the reference to the Texture2D can suddenly be null, because the AssetPreview class does not know my List, so I'd rather expect the content of the Texture2D to be removed when it is removed from the cache and not the reference to it. But whatever..