Search Unity

Tilemap: Resizebounds() And Clearalltiles() Leaving Orphaned Tile Resources

Discussion in '2D' started by eightpoundgorilla, Apr 14, 2019.

  1. eightpoundgorilla

    eightpoundgorilla

    Joined:
    Jan 24, 2014
    Posts:
    5
    So I have created an endless terrain generator using an isometric tilemap. Rather than implementing a chunking system I am actually updating the tilemap every time the player moves to a new tile. Basically it looks something like:

    Code (CSharp):
    1. Start() {
    2.      Tilemap.size= new Vector3Int(xSize, ySize, 1)
    3. }
    4. FixedUpdate() {
    5.      if(currentCell != previousCell)
    6.      {
    7.          Tilemap.origin = player's new location;
    8.          Tilemap.ResizeBounds();
    9.          Tilemap.CompressBounds();
    10.          RecalculateTiles();
    11.     }
    12. }
    This actually works exactly like I want it to and performs quite well... sorta.

    According to the documentation: "Tiles outside of the bounds will be removed from the Tilemap," and this works as expected. It may be that I don't have a complete understanding of the feature, but it seems like if the tiles are removed that they should also be destroyed. However, the tiles remain in the scene with 0 reference counts and just continue to eat more and more memory.



    After searching the forums a bit I learned that these are not managed objects and therefore not subject to GC.

    https://forum.unity.com/threads/mem...-gc-ed-when-re-allocated.513961/#post-3365665

    "The rule-of-thumb is that if the type inherits from UnityEngine.Object, it lives in C++, and you're handling a representation of it in your C# scripts."

    Now my fix for this is as follows:

    Code (CSharp):
    1.      TileBase[] originalTiles = tilemap.GetTilesBlock(tilemap.cellBounds);
    2.      tilemap.origin = origin;
    3.      tilemap.size = size;
    4.      tilemap.ResizeBounds();
    5.      tilemap.CompressBounds();
    6.      TileBase[] newTiles = tilemap.GetTilesBlock(tilemap.cellBounds);
    7.      TileBase[] removedTiles = originalTiles.Except<TileBase>(newTiles).ToArray();
    8.      removedTiles.ToList<TileBase>().ForEach(t => Destroy(t));
    I'm OK with this, but is there any reason why ResizeBounds() couldn't handle this? Also, ClearAllTiles() behaves the same way.

    Edit: I should point out that if all my above assumptions are correct, I would only expect these methods to clean up unreferenced objects (e.g. I may be storing Tiles in a collection for the purpose of re-usability.)

    Cheers
     
    Last edited: Apr 17, 2019
  2. ChuanXin

    ChuanXin

    Unity Technologies

    Joined:
    Apr 7, 2015
    Posts:
    1,068
    Sorry about this issue! If you could file a bug with your project using the Unity Bug Reporter and post the case number here, that would be helpful, thanks!
     
  3. eightpoundgorilla

    eightpoundgorilla

    Joined:
    Jan 24, 2014
    Posts:
    5
    I wasn't really sure if this was a bug or if the feature was working as intended so I started by soliciting some feedback first.

    I went ahead and submitted a bug. The case# is 1146884.

    Cheers
     
  4. ChuanXin

    ChuanXin

    Unity Technologies

    Joined:
    Apr 7, 2015
    Posts:
    1,068
    Thanks! Will check this out.