# Fog Of War

Hi!

I try to realize fog of war in 2D strategy. If bot explore piece of fog it gives him some experience.
I did:

1. Tilemap with Tilemap Collider 2D.
2. Bot with Script:
``````  void Start()
{
_thisMainModel = GetComponent<MainModel>();
_thisBotModel = GetComponent<BotModel>();
_tilemapGameObject = GameObject.Find("Tilemap_FogOfWar");
_tilemap = _tilemapGameObject.GetComponent<Tilemap>();
}

private void Update()
{

{
}
}
``````

This code doesnâ€™t work correctly. It removes only some tiles in radius (screenshot attached). I have spent few days, but without resultâ€¦
What I did wrong?

Hi.

What do you expect to happen when you do your Physics2D.CircleCast?

I would simply do a distance check between the current center point of the view area and all the tiles in a rectangular area near your center point. If the distance to a tile is smaller than or equal to your radius, you show the tile. This way you will get a circular area around your character. However, this doesnâ€™t work as is, if you need to get a capsule like shape towards your view direction.

I expect that it return hit point inside circle (sight radius). Then remove this tile in that point.

Could you help me how to do it? I have no idea how take tiles from tilemap from rectangleâ€¦

Itâ€™s ok because sight radius is circle.

â€śI have no idea how take tiles from tilemap from rectangle.â€ť

You can simply get your characterâ€™s position, and then calculate minimum and maximum corners, and get tiles in that area using GetTile, or use GetTilesBlock:

You could also simply check all the tiles in your tilemap if it is a small map. When you get it working, you can optimize it if need be.

When you have the tiles, you can iterate through all the tiles, and check the distance.

1 Like

I realize some keywords might help you, these might not be obvious/easy to find simply by reading API docs.

See tilemap cell bounds, it is very useful, you can use it to get the area you have used for your tiles in grid:

``````var bounds = tilemap.cellBounds;
``````

Note that any used then erased areas are there AFAIK, you can remove those using:

``````yourTilemap.CompressBounds();
``````

To iterate tiles, you can use cell bounds min and max, youâ€™ll get the idea from this:

``````for (int y = bounds.min.y ; y <  bounds.max.y ; y++)
{
// iterate x too
// then do stuff here
}
``````

There is more in cellbounds, allPositionsWithin is very useful to get all the positions in cell bounds area:

``````foreach (var pos in map.cellBounds.allPositionsWithin)
{
// do stuff here for each position
}
``````
1 Like

eses, Thanks a lot! Itâ€™s working!

But problem is tilemap collider not equal tilemap bounds. And I need check many empty tile (screenshot attached - red lines). Maybe you know how can I optimize it?

I really donâ€™t know what part is working for you and what is not.

You donâ€™t need any colliders for this to work.

With tilemaps that most likely is the case.

You are not doing collision checking against some physics shape in this case.

You only need the positions, and then you can step through all the positions in area, get the tile at position x,y (whatever that is in that step) and set that on/off (or change the tile, or whatever) based on the distance.

Now I must check many tilemap cells (also without tile inside):
_tilemap.HasTile(position)

Maybe there is more optimal way?

My code is:

``````  private void Update()
{
BoundsInt bounds = _tilemap.cellBounds;

foreach(Vector3Int position in _tilemap.cellBounds.allPositionsWithin)
{
if (_tilemap.HasTile(position) && Vector3.Distance(_thisBotModel.transform.position, position) <= _thisBotModel.SightRange)
{
_tilemap.SetTile(_tilemap.WorldToCell(position), null);
}
}

_tilemap.CompressBounds();
}
``````

â€śMaybe there is more optimal way?â€ť

I suggest you read the docs. See Tilemap class and its methods.

You can get a rectangular area instead of full map like I already mentioned earlier.

Why are you doing the CompressBounds after the operation? You should do it first, possibly once in Start, if required at all.

There is also SetTiles, which allows you to set several tile coordinates at once. You give it a list of coordinates and tiles. It should be more performant than setting single tiles in a loop.