Unity 2D Tilemap, and ever increasing Total Object Count
Hi all,
I'm creating a game that uses an 80x40 2D Tilemap, using procedural terrain generation. Currently, creating the map works flawlessly, as well as re-building with a button press (as many times as I want). And, I'm getting really great graphical performance (~800 of FPS).
However, I'm noticing that every time I rebuild the map, I get an increasing Total Object Count in the Profiler-memory section. The increase per map re-build is around 2500 to 2700 objects. This is not quite the full amount of tiles (3200) but is close enough that I suspect the sprite drawing as the source of the leak.
Reading online indicates that there is potentially a memory leak with the Material renderer. I'm not sure if the method I'm using to redraw the map falls within this category or not. Here's how I'm doing it...
I have a bunch of sprite atlases... for various auto-tiling terrain types. Essentially, I do the following...
Vector3Int v3 = new Vector3Int(0, 0, 0);
TerrainTile theTile = ScriptableObject.CreateInstance<TerrainTile>();
for (int x = 0; x < theWorld.Width; x++) {
for (int y = 0; y < theWorld.Height; y++) {
int nValue = theWorld.squares[x, y].tN_value[tType];
theTile.sprite = Terrain_atr.GetAutoTileSprite(nValue);
theTilemap.SetTile(v3, (TileBase)theTile);
}
}
GetAutoTileSprite just grabs a sprite from a sprite atlas based on an auto-tile rule.
So, does the above method of painting sprites fall into the Material renderer memory leak?
I can't find any other source of objects in my code, as I simply reuse all variables every time I rebuild the map... I'm not (as far as I can see) creating anything new.
Thanks for any insight.
Answer by MartinTilo · Sep 07, 2019 at 08:12 AM
I don't know about any Material memory leak regarding sprites. Generally assigning to the .material property instead of .sharedMaterial will create a copy of the material. However, in your case you might be leaking Scriptable Objects in form of your TerrainTiles. Anything that you manually create, that is inheriting UnityEngine.Object needs to get Destroy()ed (and the reference nulled) when it is no longer needed, to free the underlying native resources. It won't be garbage collected for you by just abandoning it. You might also want to use the New Memory Profiler Package to take a snapshot before and after the map rebuild and then diff the two, to see what's still around. Also, at least for testing purposes, you might want to call GC.Collect and UnloadUnusedAssets before each capture, to get a cleaner picture.