A lot of the core systems for Mercury Fallen are in place and a lot of my work has been focused on getting in the game play content. This, as always, is proving more of a challenge than I originally thought, but proper planning goes a long way. There has been one lingering system that I had been avoiding as I thought it would be a real challenge, but, as it turned out, I managed to get it done pretty quickly.
Urban Dictionary defines Fog Of War as “The unavoidable aspect of war wherein the intelligence gathered is always incomplete to a degree, thereby making any decisions concerning said war a bit… foggy.”
For those not familiar with the term, a Fog Of War is when part or all of a game map is hidden until the player directly or indirectly discovers the area. This is common in strategy games in the case where a player can’t see enemy movement unless they have some of their own units in the area. For Mercury Fallen this meant visually hiding all the areas of the game environment until the colonists have seen/explored it.
This has been something I’ve wanted to add to Mercury Fallen from the start, but just recently built a system for it. I wanted to ensure areas unexplored by your colonists were not visible to the player which encouraged mining and exploration in all directions. There are two things I had to consider when building the system; How do I determine what tiles are visible and how do I visualize that data?
While Mercury Fallen is 3D the data sits on a 2D grid which makes some things easier and other things harder. My initial approach to colonist vision included three elements.
Range: How far can the colonist see from their current position.
Field Of View: The colonist could only see tiles within a view angle in front of them.
Line Of Sight(LOS): I didn’t want colonists seeing through walls so I needed to know what cells might block other cells.
The above image illustrates the range and view angle of a given colonist using Unity Editor gizmos.
From a coding perspective the first two elements were fairly easy. First I generated a collection of cells in a circle around the colonist. For each cell in that circle I test if the angle to it is less than the view angle and if it is then it’s in our field of vision. The third element proved to be a little more complicated.
LOS in many games usually uses ray casting to determine a collision from the point of view to the target. This is a fairly common and easy way to do visibility testing. While I probably could have used this approach, it would have required additional collider generation data that I didn’t want to add for every cell. Instead I decided on using a line generation algorithm to do some custom ray casting.
For every cell within the colonists field of vision I calculate a line from the colonist to the target cell. I can then iterate over each cell in the line and if any cell within that line is set to block LOS then I know I can’t see the target cell and discard it.
The end result of the calculations is a set of cells that the colonist can “see” which I can then hand over to the Fog Of War system to update it’s visualization.
My first approach to this was to generate a mesh in code that had it’s vertices aligned to the cell grid. This would be above the cell visuals and for each tile that is “seen” I could update the alpha/opacity value of the related vertex in the Fog Of War mesh. Using a vertex color shader I could then punch holes in this black overlay so that only explored cells would be visible.
After getting that working with a custom shader to show the vertex colors I didn’t like how it looked. The gradient from a transparent cell to a solid cell was too vivid and I wanted a softer look to it. I also didn’t like the idea of this dense mesh constantly being in the scene so I tried a different approach.
The second approach only involved generating a single quad that would sit above the game environment. I then created a texture object in code that was the same pixel dimensions as the grid itself. Each pixel in the texture related to each cell on the grid and I could update a pixels alpha/opacity value for visualization of the Fog Of War. Stretching a small texture over such a large area had the natural effect of a soft blur on the edges between seen and unseen cells. The end result matched what I was looking for.
I was pretty happy with the end result. I ended up removing the colonist field of view as it generated results that were accurate, but didn’t feel right. Now back to more game play implementations.