but
every single guide I've seen out there to implementing fog of war in unity is absolutely fucking awful. like just some real "here's what will get you results but will also be the absolutely least efficient shit around, to the point where your fog of war implementation will likely have the highest overhead out of any of your game's systems" kinda shit, y'know?
like the most common advice I see is "put a plane above your entire map and assign a read/write texture to it. when you want to reveal areas, use SetPixels() to change the alpha channel or whatever. now, if you've used unity, you're probably already going "wait I'm sorry what" but if you haven't used unity, I'll give a rough overview of why this is a mindbogglingly bad idea
the first reason is obvious: SetPixels() is fucking slow. even the faster SetPixels32() is slow! they're both faster than SetPixel() but the moment you hit Apply(), you're going to see a noticeably dip in performance, especially the higher the resolution of your fog of war texture. this can become a problem even on modern machines! you're fundamentally bottlenecked because you're trying to move this data from system memory to the gpu! that's slow
but also, SetPixels() and SetPixels32() also has another annoyance: they only accept 1 dimensional arrays. this makes working with them just a bit of a pain? if you want to pass in a specific area to change, you're basically going to have to implement a modulo function somewhere so you can pass actual coordinates in there and really this is something that unity themselves should have implemented as an overload *like over a decade ago BUT I DIGRESS. this is one of those things where you'll have to be consciously aware of what you're doing
and like, here's the shit
here's the real shit
all these guides also push all this stuff right through in Update()! FUCKING EVERY FRAME THEY'RE DOING THIS SHIT! Applying SetPixels() even when just units were moving would be bad enough! the naive approach being recommended here is almost always being done by the individual unit too, so what these guides tend to recommend is calling an expensive function that will increase in cost linearly the more units you have revealing the map!
there are some obvious improvements that can be made here. a simple one is to make it so that Apply() is called once per frame at most. Make it so that units change the state of the fog of war array that contains whether a tile is revealed when they're moving and, if they do do that, make it so they set a bool associated with that array called isChanged or something to true. then, somewhere in an update loop, check that variable and, if it's true, then update the fog of war
of course, there's still problems here. for the most part, SetPixels() has a cost that will increase by roughly 4x for each incrementation of a power of two texture size. if you want a higher resolution texture, jumping from a 256px one to a 512px one will increase how long Apply() takes by a fucking lot. it sucks! this advice sucks! it becomes needlessly cumbersome and slow really quickly! and the worst part is that I've actually seen a LOT of games made with unity that implement fog of war literally do this! I've watched as the framerate struggles the more units there are or every time the fog is updated!
and so like... I actually had to spend a lot of time trying to figure out what to about this in my own implementation, and I think I've settled on something that actually works
- an orthographic camera above the scene points straight down at the terrain. this camera's size is set so that it always has a full view of the battlefield
- said camera only renders a single layer. this layer contains nothing but scaled geometry that represents each unit's field of view. the result is a black and white (well, red and white because I use an R8G8 texture where only R is currently used but WHATEVER) view from the camera that represents how much of the map is visible
- I access the camera's render texture from a post processing shader applied to the main camera. all this really requires is reconstructing world position from depth normals and doing some remapping based on the size of the orthographic camera
- I apply a couple noise textures because I Just Think They're Neat
- I save this render texture to a file when the the player save their game. I even have a special function for this specifically so I can save images without interrupting the rendering or anything. no hitches
- to load this data, I just load up that image file and blit it to the render texture
- SetPixels() exists, but is entirely a last resort. if, for some reason, loading the texture fails, it'll instead load from the fog of war array data that's used for various gameplay reasons. from there, I pass that on to SetPixels() to restore the fog of war
is this more complicated? yes? is it also blazingly fast? also yes. does it also look cool despite having a really small texture size thanks to creative use of noise textures? yeah, I think so!

