Hello everyone! We are a married couple of game developers with two cats:
- Magdalena (pumax) Świderska - artist
- Marcin (sfider) Świderski - programmer
- Kira and Dante - cats
We both work as professional game developers at Flying Wild Hog, a polish studio responsible for a revival of classic FPS game Shadow Warrior.
For some time we were thinking about creating a game together. Unity 2D Challenge turned out to be a great incentive to go from thinking to doing. That's how the DEEP SEA COLONY came to be.
DEEP SEA COLONY is an underwater city builder game in which the player has to take care of both physical and mental needs of his crew. The story begins with some worldwide catastrophic event that forces a crew of deep sea science/mining station to transform their temporary habitat into long-term self-sustained colony. The newborn society will have to maintain and expand their infrastructure in a harsh environment of 200m below sea level. They will have to overcome the stress of living in confinement with people they didn't plan on spending the rest of their life with. The constant fear of being crashed by the immense pressure will weaken the mental stability of event toughest crewman which will lead to paranoia and hallucinations. The only way to survive is to build and maintain the safest and most efficient colony possible with lots of cats on board to keep the crew company.
The above is what we aim for in the long run. For this challenge, with only 6 weeks of after hours work, we were able to accomplish a very simple simulation of the colony with really nice 2D graphics.
For this project we used 2D Hexagonal Tilemap, 2D Cinemachine and 2D Animation. We also developed set of tools for editing the map for our game. You can read about them in Terrain Tools section. The final submission was prepared with Unity 2018.2.17f1.
All the assets, including sprites, animations, shaders and scripts, were done during the 6 weeks we spent on this prototype. We also used some free audio for the game and video. Credits for the audio can be found at the bottom of this page.
I, the programmer, really liked the idea of making a game on a hex grid. As the 2D Hexagonal Tilemap is one of the technologies the challenge is based on, we decided to build our game around it.
From many ideas that we had, including a dark lovecraftian isometric dungeon crawler, we chose a city builder with underwater theme. We both like games like Banished and The Settlers 2, and the hexagonal grid is great for building nice organic settlements. We came up with the underwater setting because we like the idea of surviving in harsh and unforgiving environments but Mars was already taken.
As you can see on the Prototype Preview video, we have some basic gameplay features present. The colonists can find their way around the colony and even can take shortcuts through the water. We have a work distribution system that assigns tasks, like building, resource delivery and work station operation, to citizens that have nothing better to do. If there's no work at the moment, colonists will just stroll through the tunnels so there's always a feeling of busyness. We have very simple production chain with glass and steel being produced from sand and iron ore which are extracted by Gatherer building.
With the prototype we were able to test the automatic stalker camera. It came out rather well and we will definetly improve on it. For implementation details please look into Cinemachine section of this page.
One of the features that was toughest to maintain but indispensable during development was the save system. We tried to keep it stable at all times, so we could test our solutions not only from the fresh start, but also on an already developed colony. We even have autosave feature in editor that saves the game right before leaving the play mode.
First off we needed to decide what art style we want for out game. So I (pumax) sketched few ideas. Here are some of them:
We chose a sketchy style :) After that I created more finished version with multiple colour variants.
Living Quarters form first idea through a concept art to the final in game version.
The main goal of the design of buildings was to give them underwater feeling and make them consistent. To achieve this I incorporated common elements (e.g. doors, yellow handrails, water gates, lights, tanks and containers) in each of the buildings.
Ok, we have buildings... Now we need to have some tunnels and intersections with water gates that will help our fellow colonists move quickly from one place to another (It's always nice when you don't need to dress up into an underwater outfit to go from work to home).
Important thing is to create nice looking underwater ground tiling texture. It wasn't an easy task, due to hexagonal shape of the tiles, but I think it ended up looking really good.
Most comfortable and pleasing task was to create environment elements like rocks and flowers.
I created few more that I decided to not use in current version
Here's some process gif from creating one of the bigger rocks.
Decoration object palette for use with our Terrain Tools
Resources icons used on the UI.
The first thing to do, from the technical side of the project, was a set of tools for creating the underwater landscape. This feature makes a heavy use of 2D Hexagonal Tilemap. There's also a Sprite Editor module that was helpful.
Basic Hexagonal Tilemap
The base for the terrain is a Hexagonal Point Top Tilemap with tiles 1.28 units wide and 0.85 units high. Width to height proportion comes from perfect hexagon (all angles of 120 degrees) viewed from isometric camera (angle of 35.264 degrees from the terrain plane). Calculations go something like this:
height = 1.28 * 2 / sqrt(3) * sin(35.264 deg) = 0.85332512559
The width comes from the size of tile sprite: 512 pixels with 400 pixels per unit.
I didn't like the idea of each hex being drawn from a rectangular sprite using alpha blending. It's not optimal from performance point of view and the burden of prepering perfectly aligned hex sprites lands on the artist. To solve this I scripted a simple Sprite Editor module that sets the perfect hex outline in the sprite with a click of a button. Tile sprite prepared in this way can be drawn using opaque shader and will align without visible seams with other tiles in the tilemap.
Terrain with Depth
Flat terrain seemed like a dull choice for rich underwater environment. To give it some depth we had to make a few improvements:
There are total of 5 tilemaps, each offset by -0.13 units on Y axis from the one above it. This gives us 5 height levels on the map. It's enough to have some depth but not care about high areas covering lower ones.
The Sprite Editor module generates two sprites from a tile texture: one for top side and one for the front side.
Tilemaps are rotated around X axis and each tile is rotated back using TileData transfrom to face the camera. Combined with opaque shader used on tiles, this allows for depth resolution using depth buffer. In this way we didn't have to figure out how to Z-sort tiles between multiple tilemaps.
There's a special TerrainGridBrush that works on all terrain tilemaps at once. The basic idea is that when you paint a tile on a tilemap, the same tile is painted on all tilemaps below and erased on all tilemaps above. Similarly, when a tile is erased, it is also erased on all tilemaps above.
The TerrainTile script does also look into neighbouring tilemaps to decide if it should display top or front side of the tile.
Terrain Tiles Variations
The next step was to add some variation to the terrain. We started with additional tilemap for flat decoration tiles with small terrain features like rocks. There's only one such tilemap, but each tile sets its TileData.transform to match the height of corresponding terrain tile. Terrain tiles also refresh decoration tiles so if we modify terrain height the decoration will move automatically.
Using TileData.transform for height control means we cannot use GridBrush flip feature (or so I came to believe). For that reason each decoration tile has additional flipped version. This is handled in the decoration tile script.
Both terrain and decoration tiles are painted using our custom TerrainGridBrush. To make our work easier, the brush will paint terrain tilemaps only with terrain tiles, and decoration tilemaps with decoration tiles. There's no room for human error.
Vegetation and Massive Stones
With just the small features we still have quite dull landscape. So we introduced yet another tilemap on which we place prefabs with combination of vegetation, medium rocks and massive stones.
Prefabs are placed using custom grid brush DecorObjectBrush. The brush allows for picking prefabs directly from the project view and supports flipping on X axis. Similarly to decoration tiles, decoration objects are updated during terrain modifications and can only be placed on compatible tilemaps.
Depth Resolution problem
Placing properly Z-ordered sprites on a tile introduced a new problem with depth resolution.
Terrain tile sprites were placed in the back (on Z axis) of the tile so every sprite placed on that tile would draw on top of it. This caused the effect from the image to the right.
To solve this issue the shader used to draw terrain tiles "broke" tiles in half and aligned them to tile borders as can be seen on the animation on the right.
This solved the problem and the effects can be seen to the right.
To achieve true underwater feeling we used Unity Post Processing Stack combined with some custom shaders and particles.
Fog and DOF
To imitate the way light travels through sea water we used blueish Fog and slight Depth of Field effect.
For fog we developed custom shader that used distance from camera for depth information. In case of terrain tile sprites we used some additional math to calculate true vertex depth hence the smooth gradient.
We used the same math formula in terrain tile shadow caster shader to fill depth buffer for use in Depth of Field effect.
In the depths of the ocean you are never alone. There are always thousands of small creatures floating around you. To capture this we used multiple particle systems that simulate small floating organisms in front of the camera. We didn't want post processes to affect them, so they are rendered using secondary camera directly to the main render buffer.
One of the charms of playing city builder games we like is the ability to follow your citizens around. If there's nothing important take care of, you can just lay back and chill, watching digital people attend to their chores. In our game we would like to have a system that would choose the most interesting activities in our colony and automatically focus on them. 2D Cinemachine is a great base for this.
In the prototype we have a CinemachineVirtualCamera following each of our colonists. The idea is that the script running the colonist would set a priority for the virtual camera based on some form of fun factor of the activity the colonist is performing. For now the priority is set at random, between 1 and 10, in a few seconds interval.
For the player controlled camera we have an invisible object, called the pointer, that can be moved around the map using keyboard or mouse. The pointer is followed by a CinemachineVirtualCamera with the priority set to 20.
The player can, at any time, switch between manual camera and our automatic camera system by setting the priority of virtual camera following the pointer from 20 to 0 and back. There's also an option to lock the automatic camera on specific colonist by setting the priority of his virtual camera to 15.
For all our virtual cameras we use Framing Transposer and Confiner. For the pointer we use zero dead and soft zones and zero damping. For the colonists we use some small values, so the target is in the center but has some degree of freedom. We always preserve the 10 units distance, which is important for our post processes. The CinemachineBrain updates in LateUpdate so the virtual camera following the user controlled pointer has no delay.
For the prototype we prepared one character and animated it using 2D Animation tools. Below you can see basic movement animations, walking and swimming, with and without the box, in 3 basic directions. With just brief prior experience with animation software we were able to achieve this effect in just a few hours.
For vegetation animation we combined Skin Weights And Geometry Editor from 2D Animation tools with procedural vertex animation using custom shader. The geometry editor allowed us to fine tune sprite mesh triangles.
The effect is rather subtle:
Thank you for your time!!!
Underwater [Loop] AMB by DCSFX | https://www.freesound.org/people/DCSFX/
Sound promoted by https://freesound.org
Secret Locations by Nicolai Heidlas | https://www.hooksounds.com/author/nicolai-hs
Music promoted by https://www.free-stock-music.com