In Atmocity, the goal is to build a large, gravity defying and super efficient city floating in the sky. Efficiency being a bit of a key word. Each building has an output, be it population from residential zones, goods from industrial zones, various types of resources such as steel, bioplastics or water from steel mills, plastic manufacturing plants or water absorbents respectively.
Each building requires a set of inputs and several conditions to be met to function at maximum efficiency. For instance, for residential zones to grow to their max density, they must be in the vicinity of parks and school, and they have to have enough food, electricity and water. Buildings whose requirements are not met will produce less.
When cities are small, this will generally not be an issue. Players will be able to click on each building and check the current outputs and efficiency level. But as the city grows, this will become all the more time consuming and difficult. Since the city is also a living organism affected by the state of the local and global economy, a shift in the demand for certain goods or a policy implementation from the player, might drastically shift the balance of the city. A sort of butterfly effect if you will.
To give players a quick overview of how well buildings are performing I wanted to implement a type of color coded depiction of the city, similar to a heat map. I already had the efficiency variable available in the resource management system, so "all" I needed was to input this into some sort of system.
The visual concept I came up with looked like this:
Buildings in green are performing at their maximum, while the red one has missing resources or has been placed near an undesirable building.
What I wanted to make was a system that allows for quick transitioning between the regular view and the efficiency view. Given the intended size of the cities, switching out materials one by one was not a good solution. I also had no concept of how to build this using a screen space effect or if this was even possible.
So I resorted to using a replacement shader. From a C# perspective this is fairly straight forward:
This code gets the RenderType from the ReplacementShader and instantly replaces it in the scene. Buildings in Atmocity uses their own Unity standard surf shader, where the RenderType tag is called "OpaqueConstructs". This allows me to hide things like trees, sun/moon and some of the many props scattered around the city and only render a very basic view of the city.
The main work is then done in the replacement shader, where the new interpretation of "OpaqueConstructs" occurs.
The shader itself gives all the buildings a gradient based on their height. To take efficiency into concern, each building's efficiency value is fed into a float via a MaterialPropertyBlock when the replacement shader is activated. Using a MaterialPropertyBlock ensures not breaking the sharedMaterial that is used by all buildings to turn on lights during night time in the day/night cycle. It also preserves memory as buildings won't require an own instance of each material.
The end result allows taking the normal view of the city:
And cycling through the efficiency float values via material property blocks into the shader to display building efficiency as:
Green buildings are performing at 100% efficiency, while red is performing very poorly, yellow in between. This allows players to home in on problematic neighborhoods and address issues. It also lets players find out if there's a lack of supply for specific buildings.
From the efficiency view image above, there was a park displaying in a yellowish tone. Clicking it gives us the exact efficiency (50%) marked with a cog icon. The missing consumable in this case is low skilled workers. The player can then adress this by building more residential zones that cater to low skilled Labour or (in the final version of the game) adjusting policy such as forced labour or increasing health levels to allow people to work longer (residential zones create more labour force output).
That's it for this tutorial. Hope it was helpful. Feel free to ask me questions any time here or on Twitter.
/ Dispersing Minds