Search Unity

Getting and storing tilemap positions into a 2D array

Discussion in 'Scripting' started by sniffle63, Feb 13, 2019.

  1. sniffle63

    sniffle63

    Joined:
    Aug 31, 2013
    Posts:
    365
    Hello im using this method to store tilemap positions into a 2D array from 0, 0 to the tile maps bounds.x and bounds.y

    The way im doing it seems a bit convoluted, so i just wanted to post and see if anyone had a better idea


    Code (CSharp):
    1.   bounds = tilemap.cellBounds;
    2.         spots = new Vector3Int[bounds.size.x, bounds.size.y];
    3.         TileBase[] allTiles = tilemap.GetTilesBlock(bounds);
    4.  
    5.         tileWorldLocations = new List<Vector3Int>();
    6.  
    7.         foreach (var pos in tilemap.cellBounds.allPositionsWithin)
    8.         {
    9.             Vector3Int localPlace = new Vector3Int(pos.x, pos.y, pos.z);
    10.             if (tilemap.HasTile(localPlace))
    11.                 tileWorldLocations.Add(localPlace);
    12.             else
    13.             {
    14.                 localPlace.z = 1;
    15.                 tileWorldLocations.Add(localPlace);
    16.             }
    17.         }
    18.         for (int x = 0; x < bounds.size.x; x++)
    19.         {
    20.             for (int y = 0; y < bounds.size.y; y++)
    21.             {
    22.                 TileBase tile = allTiles[x + y * (bounds.size.x)];
    23.                 Vector3Int position = tileWorldLocations[x + y * (bounds.size.x)];
    24.                 if (tile != null)
    25.                 {
    26.                     spots[x, y] = new Vector3Int(position.x, position.y, 0);
    27.                 }
    28.                 else
    29.                     spots[x, y] = new Vector3Int(position.x, position.y, 1);
    30.             }
    31.         }

    To be clear, this works fine. Just doing an optimization pass on my code and this area seemed like it needed fixing
     
    Last edited: Feb 13, 2019
  2. sniffle63

    sniffle63

    Joined:
    Aug 31, 2013
    Posts:
    365
    yeah was definitely convoluted. Not sure why i was doing it that way.

    If anyone can think of a better way then this, id love to hear from you <3

    Code (CSharp):
    1.      
    2.   spots = new Vector3Int[tilemap.size.x, tilemap.size.y];
    3.         for (int x = tilemap.origin.x, i = 0; i < (tilemap.size.x); x++, i++)
    4.         {
    5.             for (int y = tilemap.origin.y, j = 0; j < (tilemap.size.y); y++, j++)
    6.             {
    7.                 if (tilemap.HasTile(new Vector3Int(x, y, 0)))
    8.                 {
    9.                     spots[i, j] = new Vector3Int(x, y, 0);
    10.                 }
    11.                 else
    12.                 {
    13.                     spots[i, j] = new Vector3Int(x, y, 1);
    14.                 }
    15.             }
    16.        
    17.         }
     
    Last edited: Feb 13, 2019
  3. eses

    eses

    Joined:
    Feb 26, 2013
    Posts:
    2,637
    @sniffle63

    Not better, but just slightly different, nothing else...

    I've never seen such for loops, so I modified you code a bit. Got rid of those double variables in for loops.

    Also, if you happen to paint outside min and max area of your final tilemap, it's bounds will extend beyond existing tiles, so it might be good idea to either do compress from tilemap menu, or from code (I think I did read it's quite expensive though).

    Code (CSharp):
    1. tilemap.CompressBounds();
    2. var bounds = tilemap.cellBounds;
    3. spots = new Vector3Int[bounds.size.x, bounds.size.y];
    4.  
    5. Debug.Log("Bounds:" + bounds);
    6.  
    7. for (int x = 0; x < bounds.size.x; x++)
    8. {
    9.     for (int y = 0; y < bounds.size.y; y++)
    10.     {
    11.         var px = bounds.xMin + x;
    12.         var py = bounds.yMin + y;
    13.  
    14.         if (tilemap.HasTile(new Vector3Int(px, py, 0)))
    15.         {
    16.             spots[x, y] = new Vector3Int(px, py, 0);
    17.         }
    18.         else
    19.         {
    20.             spots[x, y] = new Vector3Int(px, py, 1);
    21.         }
    22.     }
    23. }
    I hope I got it right... but the idea should be clear I think.
     
  4. sniffle63

    sniffle63

    Joined:
    Aug 31, 2013
    Posts:
    365
    Hmm interesting, didnt know about tilemap.CompressBounds(); I should only need to do it before the game starts because the world, atm, isnt procedural. So it should be fine to do it threw the tilemap menu you referred to. Ill have to look into it tho. I was using the bounds size at first, but sense i wasnt aware of the compress bounds, i didnt see a point of using it over the tilemap size.

    Thanks for the info!


    *EDIT*
    I dont see a way to compress the bounds threw any menus, only threw code
     
    Last edited: Feb 13, 2019
  5. eses

    eses

    Joined:
    Feb 26, 2013
    Posts:
    2,637
    @sniffle63

    It's in Inspector Reset menu of Tilemap.

    Better to run from there to make it permanent (run during edit mode that is), but to be sure that your map is limited to visible bounds, do the bounds compress from code. But if your tiles are procedurally generated then you can't have manual painting errors I guess.
     
    sniffle63 likes this.