Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Voting for the Unity Awards are OPEN! We’re looking to celebrate creators across games, industry, film, and many more categories. Cast your vote now for all categories
    Dismiss Notice
  3. Dismiss Notice

"Fog of War" shader for tilemaps

Discussion in '2D' started by zipper9998, Jul 30, 2018.

  1. zipper9998

    zipper9998

    Joined:
    Dec 24, 2015
    Posts:
    10
    Hi, I am wanting to create a shader for a tilemap which only reveals tiles which are around the player and persists this, so when the player moves away, the tiles that he has already seen remain visible. I have tried to do this with a script but this seems to be inefficient and I feel a shader is the best approach. I am, however, unsure how I would create such a shader, would the tilemap shader work per - tile or for the whole map?

    Thanks.
     
  2. spryx

    spryx

    Joined:
    Jul 23, 2013
    Posts:
    556
    it is easier to render a black texture over top of the tiles and "poke holes" into it using SetPixel()
     
  3. zipper9998

    zipper9998

    Joined:
    Dec 24, 2015
    Posts:
    10
    ahhh thats an interesting solution, thank you! I am somewhat of a noob with unity shaders though, perhaps you could point me in the right direction, I'm unsure where to even start with doing something like that efficiently. Also, does set pixel literally "poke a hole" or is there more to it...
     
  4. spryx

    spryx

    Joined:
    Jul 23, 2013
    Posts:
    556
  5. zipper9998

    zipper9998

    Joined:
    Dec 24, 2015
    Posts:
    10
    Wow thanks very much, looks promising.
     
  6. zipper9998

    zipper9998

    Joined:
    Dec 24, 2015
    Posts:
    10
    Ok I get the idea but I'm not sure this would work for the application I'm looking for, Firstly, my game map will be procedurally generated and will be virtually infinite, so I can't put a black texture over the top. Secondly, I want things that have already been seen to remain visible forever as if the player "remembers" where he has been. Also, I feel that this approach would not fit the style of the game and I would rather have individual tiles be revealed around the player as he moves. Thanks anyway for the help though, I can see how that approach would be very useful for other sorts of games!
     
  7. barskey

    barskey

    Joined:
    Nov 19, 2017
    Posts:
    207
    Since it is tile based, could you have each tile's Sprite Renderer set to black at start, and then turn to white when you approach them? Or if you are looking for something a little fancier, add a second Tilemap coincident with the first, and each tile will simply be a solid white sprite. Then you can change the color/alpha of this "cover" tile to reveal the one beneath it.
     
  8. zipper9998

    zipper9998

    Joined:
    Dec 24, 2015
    Posts:
    10
    yeah thats the effect that Im going for, I have tried doing exactly that but its much easier said than done! does each tile have its own sprite renderer? That would make it much easier, but I believe they don't as the whole tilemap is rendered at once. Also adding another layer of tiles seems to be rather a waste of resources seeing as the map will be procedurally generated.
     
  9. barskey

    barskey

    Joined:
    Nov 19, 2017
    Posts:
    207
    Yes, it does seem like a lot of overhead. Each Tile does have its own SpriteRenderer, because each tile has its own Sprite. You could write a custom Tile based on the TileBase class, and create a method for swapping the Sprite from a black one when discovered to your assigned sprite. It is a bit more complicated since the Tile is a ScriptableObject, but there are examples about to help.

    I think this thread has an example:
    https://forum.unity.com/threads/man...-tilemap-tools-seems-to-be-impossible.500773/
     
  10. zipper9998

    zipper9998

    Joined:
    Dec 24, 2015
    Posts:
    10
    Awesome, thanks for your reply, would it not be easier to just set the sprite renderer color to white when its found and black by default rather than replacing tiles, considering as you say each tile is a sprite
     
  11. barskey

    barskey

    Joined:
    Nov 19, 2017
    Posts:
    207
    It should, but I have never tried anything like this. Nor am I in front of my Unity computer, so the figuring out is left to you! Report back when you find a workable solution because I know many others want to do similar things.
     
    zipper9998 likes this.
  12. spryx

    spryx

    Joined:
    Jul 23, 2013
    Posts:
    556
    Each tile does NOT have its own renderer. A sprite reference doesn't imply that it will also have a renderer component. The tilemaps are rendered at once. This is why it is so difficult to define behavior per tile without resorting to prefabs. The tiles are mere references for the map to use during runtime.
    https://docs.unity3d.com/ScriptReference/Tilemaps.TilemapRenderer.html
     
  13. barskey

    barskey

    Joined:
    Nov 19, 2017
    Posts:
    207
    OK, thanks for the clarification. So it seems it is rather convoluted to achieve what the OP wants.
     
  14. zipper9998

    zipper9998

    Joined:
    Dec 24, 2015
    Posts:
    10
    Yeah thats what I thought, I think the only solution is some sort of custom tile based on TileBase, I think my game may be easier to achieve in a different game engine, which is a shame because I love unity, but the tilemap API is a bit rubbish at the moment.
     
  15. Jackyjjc

    Jackyjjc

    Joined:
    Apr 12, 2015
    Posts:
    4
    Another tilemap layer on top of the existing to act as the fog layer? Then you can toggle individual tiles
     
  16. RidgeWare

    RidgeWare

    Joined:
    Apr 12, 2018
    Posts:
    67
    Yep, create a black fog layer. When a tile comes into range, simply SetTile to null for those coordinates. You can also run Physics2D LineCasts each tile your character moves to check for walls and things.

    Although it then raises the question of how you want the fog of war to look. In basic terms it would be sharp black squares everywhere, so I'm not sure how you would blend it in to make it look better.
     
  17. zipper9998

    zipper9998

    Joined:
    Dec 24, 2015
    Posts:
    10
    yeah, I like the idea and thank you for your input but, as I say, it seems like an unnecessary use of resources particularly as my map will be procedurally generated. I am not too worried about blending, but as you say this would be an issue with that solution. I think ultimately I do not wish to sacrifice performance for such a simple effect and wish to do it as cheaply and efficiently as possible with minimal extra resources. Thanks anyway though!
     
  18. theforgot3n1

    theforgot3n1

    Joined:
    Sep 26, 2018
    Posts:
    188
    Because this thread does show up high on Google, adding a separate layer for the fog of war is a perfectly good solution. The extra overhead is very small, even with a large procedural map. And if you use for example rule-tiles, you can also do blending with transitional fog of war tiles (one sprite for each type of transition).
     
  19. vonchor

    vonchor

    Joined:
    Jun 30, 2009
    Posts:
    238
    Actually you can affect individual tile’s sprite: you can, for example, just change the color of a tile to black or change its sprite at runtime. You could use a json file to specifies what tiles are unhidden.