
For years now I have been a fan of the game Subnautica, and my fascination with the oceans and marine lifeforms. That’s why I decided to delve deeper into the world of procedurally generated biomes. Even though Subnautica doesn’t use procedural generation for its map, I couldn’t help but imagine how cool it would be if they did. With that in mind I wanted to make a Biome Generation Tool for designers that can be used to create unique biomes.
In this blog post, I will go through the steps I took to achieve this Goal.
I first started off by making a plan and Trello board of things I thought would be needed for the end product. After writing down the list I started creating the Trello board. Seeing as this project would take around 5-7 weeks I created cards that held the deliverables for each week.

(Link to the trello board: https://trello.com/b/Qa7xGahl)
Week 1:
During this first week i want to focus on a few different things. Seeing as this tool will be used by designers, I want to look into creating my own custom editor window. For this i quickly sketched out a mockup for a window design as seen below.

(Sketch of Biome Designer)
On the left we see a window containing different properties, text and buttons that can be used to update the Biome. On the right we have a similar example only this one contains a big viewing area of an image of the biome type for a better visualization.
Secondly the terrain/mesh generation is of high priority so we can actually generate something to see.
Now that was done it was time to start researching biomes. I decided to look to the National Geographic website and found a few descriptions on what this means. According to National geographic a biome is an “area of the planet which can be classified according to the plant and animal life in it (Biomes, n.d.)“. Finding inspiration in our planet Earth I looked deeper into this and found that the aquatic biome covers about 75% of our Earth’s surface and is usually divided into 2 different categories (freshwater and marine) according to National Geographic (Aquatic Biome, n.d.).
Seeing this made me realize that I had not yet decided if this assignment would be based off realism (say like our planet’s oceans) or something entirely different that resembles the alien life like in Subnautica.
As this was not of great importance as of now (since i still need to research a lot of things) I decided to make a fairly generic list of biome properties that can be used with either one. This would give me the time to look further into this issue. This means that we can start by defining the initial properties of the biome we want to create. I thought of the basic things like scale, min/max plants and different lifeforms and so on. This can all be seen in the following Image.

(Sketch of properties lists)
Before i started looking into different terrain generation algorithms, I thought it was a good idea to look into creating a custom unity editor so I could have a decent base to work with right from the start.
Next i decided to create the project in Unity and link this to a github repository which can be found here (https://github.com/xsedohrx/GPE-2023-BiomeGenerator/tree/feature/terrain).
I started looking at the Unity documentation to find out how to work with custom editors. In doing so i came across multiple ways to make custom editor windows for Unity. The first was by creating a script and inheriting from the Editor as seen in the following Unity documentation (https://docs.unity3d.com/ScriptReference/Editor.html) which will give access to all of the editor variables. The other options is the EditorWindow library. After reading the documentation i came to the understanding that the Editor choice is often used when a custom inspector is needed for a custom GameObject. The Editor Window can be opened through the menu, it can be docked and are often used for a custom editor.
Since my objective is to create my own custom design tool that can be used by designers, I decided that the EditorWindow would better suit my needs. Keeping in mine that i want my project to be designer friendly i decided to use scriptable objects, giving designers a great way to update values in the editor.

(Biome Scriptable object used for Biome Designer)
I then began creating an editor window and called this tool Biome Designer. I added some variables like the Biome Scriptable Object that will be referenced to get the properties and update them in the tool. I then create multiple functions that are used to draw the UI Elements making sure to place them in the Begin/End GUILayout area. to make sure this is all displayed in a single container.
The following images show how I created the first version of Biome Designer.

(Biome Designer: Drawing the editor)

(Biome Designer: Displaying Biome properties)

(Biome Designer: Drawing the buttons)
In the editor we place the Biome Scriptable Object that we wish to generate. Now we are able to adjust the properties and generate it.
Now it was time to look into algorithms that are used for generating terrains. Seeing as the terrain will have a variety of different forms (flat, caves, canyon like, etc…) I thought a good algorithm to look into would be Marching Cubes. This algorithm is designed to convert volumetric data (typically 3D scalar fields) into a more visually appealing representation composed of polygons, such as triangles.
The first thing we need to do is specify the properties for our marching cube. We need to use the components meshfilter and the meshrenderer to update the mesh. This is done at the start by using the RequireComponent attribute to make sure that the object can never break due to not having the correct components. We also create the propeties for deciding if the terrain will be flat or smooth.

(screenshot of properties used for the MarchingCube)
In the Start Method we get the required components for the Mesh and call the following functions: PoulateTerrainMap and CreateMeshData.

TerrainMap is used to store the x,y,z positions of the terrain.
The PopulateTerrainMap function generates the terrain height map of the marchingcube by means of perlin noise.

Then the CreateMeshData function initializes the mesh data, clears any existing data and then iterates through the cubes in the terrain grid.

For each grid point the MarchCube function is called to determine its configuration (which is predetermined in the configuration tables) and generate vertices and triangles, afterwards it builds the generated data.
The MarchCube function then examines a specific cube in the terrain grid, samples the terrain values at its corners and determines the cubes configuration. Based on this configuration it generates vertices and triangles for the terrain surface. The vertices can be smoothed or flat-shaded depending on the configuration. If the config index is either 0 or 255 there will be no surface to generate because 0 will indicate being under the ground and 255 would be in the air leading to neither needing to be created for the surface of the terrain.


Finally the BuildMesh function is used to create a Unity Mesh from the generated vertices and triangles. It then recalculates the normals for shading and assigns the mesh to the MeshFilter and mesh collider components.

The following image shows the configuration table that was used for determining the values of the terrain

(The configuration table that was used in https://www.youtube.com/watch?v=dTdn3CC64sc&list=PLVsTSlfj0qsWt0qafrT6blp5yvchzO4ee, the triangle table goes on for a while as is has 255 different configurations)
Finally we can see an example of the marching cube with and without all shading configurations.

Issues I still need to address:
- Currently the tool only works properly when the game is PLAYING, this needs to be adjusted to in editor.
- When first using the tool the Scriptable object is empty which returns a null reference error until it has been added.
- Blog Sources (Consistency)
- I want to focus more on the design of WHY this product can be used and how. What will the user be creating and for what purposes.
Week 2
During our first guild meeting i received some valuable feedback on looking into designing the product more. WHY this product can be used and how. What will the user be creating and for what purposes. So lets start by looking at Subnautica.
Subnautica is a First person, Single-Player ,Underwater, Adventure, Open World, Exploration, Survival, Story driven game (GDC Subnautica Post Mortem).
In this GDC talk Jonas Bötel explains that they were at first trying to create modular mechanics or controls and that this failed because there was no feeling or emotions that the player would feel. Going back to the drawing board they tried to create gameplay from their concept art that did a great job at capturing emotions.


After showcasing at pax they received positive feedback from the public from creating the emotions that they had tried to capture in the concept art.
So what is it that I want to make? A tool that can be used to create subnautica-like environments for exploration games. So how can this product be used to play on the emotions of players?
A number of feelings I can think of that a designer might try to create with such a tool could be:
Huge open areas with something spectacular (awe or wonder) that the player can see from afar or visit.
Cramped caves that give the player the feeling of being lost, stuck or just claustrophobia.
Scary areas that might be dark and difficult to navigate due to little lighting.
Lets first look at some examples. Take earth for example.
There are a few things we need to consider when looking into our home planet and its oceans. One of those things is light.

Light is an important aspect to take into account when we look at ocean depth. According to World Atlas once the Bathypelagic Zone (or the midnight zone) is reached sunlight is no longer present. At this depth the only light seen is created by bioluminescent creatures. This is a good thing to keep in mind when looking into creating our scary/intense atmosphere.
I decided to do the same thing as the creators of Subnautica and make some awesome concept art (which can be seen below) to recreate the emotion I want the player to feel.

(Image of my beautiful concept art)
The first image shows a big open area in which huge constructions or beautiful creations can be displayed, or even a big building/explorable area which invites the player to come and explore. Next is an example of a fearful situation, this could be big open water in the depths below where the player wouldn’t be able to see much but be chased by big monster-like creatures giving the player the feeling of tension. As for the final image I wanted to capture the feeling of being stuck underwater in some kind of cave area where things or people can easily get stuck if they aren’t careful.
Now that I had put more thought into the design I wanted to be able to move around as if I was exploring the areas. I created a very simple camera controller that uses the main camera. When the player pushes a movement key (WASD) the camera will translate in the given direction.
As for the rotation this is done based on the Mouse X and Y position all of this can be seen in the following screenshot.

(Screenshot of Camera movement and rotation)
Next I created a list of transforms which can be used for keeping track of all of the positions I need for spawning things in.

(Screen shot of spawning list)
Say we want to spawn in an area in which the Player can explore a shipwreck, I can then just use that transforms position for spawning in the ship. On thing i do need to keep in mind though is how that area needs to be able to hold whatever it is that will be spawned in. Let me give an example. Say we want to spawn a shipwreck at the bottom of the ocean we need to make sure that area will be flat.
Moving on to the fish. I want to used genetic algorithms which will simulate the evolution letting fish change over time making them bigger, faster or more passive/aggressive. I decided to start looking into Genetic algorithms which would be used to generate various lifeforms in the biomes. Since I was familiar with Penny de Bijl’s courses I decided to use one of her tutorials from Holistic 3D (https://www.youtube.com/watch?v=njcVWdQEYXM&t=6s&ab_channel=Holistic3D)
Lets quickly think about our lifeforms. What do we want our fish to be able to do?
- Swim (‘obvously‘)
- be able to die
- be passive or agressive
- eat other fish
Guild Meeting 2:
During the guild meeting I received some feedback on defining the scope of this project so that it is clear exactly what the user will be able to create with this product. A conclusion of some kind so lets do that.
Week 3:
So lets do exactly that. This product will be used by designers for creating the following:
- Subnautica-like environments or biomes:
- Sandy/smooth beach like terrains and big open areas.
- cliff areas (big drops in height)
- caves
- Biomes which can:
- contain habitats
- explorable areas like shipwrecks or treasure chests
- Habitats that:
- can contain fish
- can contain plants
- can be adjusted to have more less of a specific fish
- can contain multiple fish
- Fish:
- are able to explore and look for food
- can evolve based on genetic algorithms which use a fitness function (Weights can be adjusted by the designer)
- can be passive or aggressive
- contain the following properties:
- Speed
- Scale
- Lifespan
- rotation speed
- can die
- can eat
- contain the following properties:
- Plants:
- will grow in specific areas/biomes
- Users can adjust the amount of plants that will spawn in the area
- Water Effects (can be adjusted by the designer ):
- simulate different kinds of areas(examples could be dense dark water for in the deep or dirty green water for another biome)
- properties can be changed like the density/ of the water or carrion (floating dead lifeforms in the ocean that fish eat)
Its time to start creating our first genetic algorithm. There are a few things needed to be taken into account before we start working on the algorithm. For this we need functions to think of:
- spawning
- crossover (or breeding)
- a mutation operator
- a fitness evaluation
First i want to think about how we will be spawning our fish. So my idea would be that they hatch from eggs that are created when fish breed (which we can think of as the creation of the new generation).
I created a new script called Egg which is will hold the data used for spawning fish. After a fixed amount of time the egg will hatch and spawn a fish.


Guild Meeting 3:
Since we are making a tool for creating Subnautica-like environments it could be wise to think more about the necessities, at least this is what I was told during my guild meeting. This means that evolution might not be the best way to go for this project. Another piece of feedback i received was that I was using too many images of code and would preferable see more explainations.
Week 4:
Instead of creating fish that evolve I will be creating prefabs that can be tweaked by the designers. This week i want to be focusing more on the biome and how its created.
Currently we have no way of knowing where our platforms should be. So I want to create some values that can be used by the designer. Lets start off by adding a height value. Now I need to find a way of detecting where they need to be.
Fish
As for the fish I decided to look for some models that could be used and came across the the website TurboSquid for some free models. Unfortunately the materials did not import along with the model as it was an FBX file so i quickly made some of my own. Added the Fish script to the prefab and create another script for the Fish Behavior.

(Screenshots of the Fish script and inspector)
Seeing as i had already put some thought into what my fish needed to do I just needed to implement some of these behaviors. So lets start with the basics. The first behavior I wanted to add was its swimming behavior. I create a method called MoveFish and add some very basic forward movement to it so we have something that resembles a fish moving forward.

I can now change the behavior of my fish.
This is done with the SetBehavior method from the FishBehavior script for testing the behavior switching.
I also wanted to update the movement of my fish as the previous image cant really be called fish movement.

(Screenshots of the FishBehavior script)
I add the following states to the FishBehavior script also: Turn, Flee, Feed, Explore and Die. Now I have a base to work with and i can start looking for other fish types so I again used Turbosquid to find them.

(Screenshots of other the 2nd fish type)
Lets improve the fishy movement. I wanted to look at real examples of fish and see that they rarely have a constant movement speed and that it can appear radical at times (especially when trying to capture them with a bucket). So I decided to do a little bit of research on how fish swim and after a bit of googling I came across the following website (https://earthlife.net/how-fish-swim-locomotion-movement/) in which is explained that fish that are shaped like trout their maximum speed is about 10 times that of their size. Which theoretically mean the bigger the fish the faster they can swim. On this website I also found the following table which relates to the speed fish can travel based on their length.

(https://earthlife.net/how-fish-swim-locomotion-movement/)
So lets start by changing the swimming method. I decided to use the theory found on the previously mentioned website, however my “Fish” are not measured in cm/inches but using the unity Unit measuring system so I will just use that for calculating the fish speed.
Editor
Its time to fix up our editor a little. As stated earlier one of the problems I was having with the editor Window script was that it was not working correctly from the start because of the scriptable object being set to null every time the editor would update. I decided to do a little bit more research and came across the CustomEditor attribute which informs Unity which component to act as an Editor for. This would help a LOT seeing as we can just use a component (in this case the Marching cube script) and we will have an editor for it. I created a new script called MarchCubeEditor.

I removed all of the unneeded methods like start and update and Inherit from the Editor script. I add the CustomEditor attribute and add the MarchCube as the parameter. This means Unity will know that it needs the editor to work with the MarchCube component. I add the OnInspectorGUI is a special function in Unity that allows me to create a custom interface for the “MarchingCube” object within the Unity Editor. It’s a bit like designing a form or control panel for this object. I also use the Horizontal layout to make sure both buttons (that I will need for the cube) are horizontally in line. I then create 2 buttons. The “Generate” button performs the following: it determines whether the “MarchingCube” object is set to operate in 3D or 2D mode and based on the mode (3D or 2D), it calls the appropriate functions to create a terrain map (landscape) and mesh data for rendering. The “Clear” button is simpler. When clicked, it clears or resets the “MarchingCube” object data. Finally the script changes the state of the Graphical User Interface (GUI) depending on whether the game is currently playing. It disables the GUI when the game is not playing and enables it when the game is running. This is done to prevent interactions that could affect the game when it’s not in play mode. Have a quick look at the example underneath to get an idea.

Plants
As for the plants i want to create stick to 2 different types. The first being a seaweed like plant and next would some form of mushroom. Finally I want something i can add to the seabed like Rocks.
Since it was really difficult to find any free assets for seaweed i decided to make a quick model myself in blender. I Started with a cube and started to sculpt it and used the pull tool to pull out the branches. then I started to shape the cube a little to look more plantlike. Underneath is an example of the “weeds”

(Screenshots of my weeds)
As for the Mushroom I was able to find a decent model for free (also on TurboSquid) that could be used which can be seen in the following screenshot.

(Screenshot of TurboSquid mushroom)
Guild Meeting 4:
During the final guild meeting I was told to focus on the necessities. In this case that would be making the marching cube more performant so that it doesn’t break when the cube gets larger than 64 *16 (or at least wait a VERY long time). Once that worked better I could then focus on making everything whole like bringing in the fish and post processing effects.
Week 5:
For the final iteration there are a number of things I want to fix. First the marching cube needs to be more performant. I already have a few ideas on how I want to accomplish this. Since we are currently looping times through our cube this makes the script VERY heavy. By adding a dictionary to the cube for each vertex I remove the exponential growth in the BIG O notation since looking up an index in the dictionary is way faster than looping 3 times through the cubes x,y,z index’s. Another possible fix might be using chunks for marching cubes.
Afterwards I want to start adding my fish and fix their movement to no longer collide with the terrain which I think will be achieved with raycasting. If the raycasts collide with the terrain then they will just turn away instead of moving forward.
As for the Post processing effect I will add a new gameobject to the marching cube which will hold the data for the postprocessing profile. This can be adjusted by the designer to give biomes a different effect.

I also happened to create a exporter so i could use it to help with terrain data. By using the StreamWriter library I was able to save data to a path on the computer. This data contains the component values like offset, height and terrainsurface. The reason I wanted this data was because I was not able to save gameobjects to as a prefab at run time. I could however add the amount of Marching cube objects I needed to the scene and add the values to each marching cube.
Conclusion:
Feedback i had received during the project was mostly positive and that there was potential, this tool could in fact help speed up the process of designing Subnautica-like biomes.
In the future I would like to add extra functionality like being able to choose things like how many biomes you would like to see, points of interest which have their own properties that can be adjusted by the designer. It would also be nice be at a point where it would be publishable in the asset store.
Sources:
Biomes. (z.d.). https://education.nationalgeographic.org/resource/biomes/
Biomes. (z.d.). https://education.nationalgeographic.org/resource/biomes/
Boris. (2021, 12 november). Marching Cubes tutorial. BorisTheBrave.Com. https://www.boristhebrave.com/2018/04/15/marching-cubes-tutorial/
Procedural Content Generation Wiki. (z.d.). http://pcg.wikidot.com/
b3agz. (2019, 10 november). How to make 7 days to die in Unity – 01 – Marching cubes [Video]. YouTube. https://www.youtube.com/watch?v=dTdn3CC64sc
Procedural Biome Generation: Ooze-Style – PROCJAM Tutorials. (z.d.). https://www.procjam.com/tutorials/en/ooze/
Whelan, N. (2020, 9 oktober). The ocean zones. WorldAtlas. https://www.worldatlas.com/articles/the-5-layers-of-the-ocean.html
How far does light travel in the ocean? (z.d.). https://oceanservice.noaa.gov/facts/light_travel.html
Holistic3D. (2022, 13 april). Learn Genetic Algorithms Programming in Unity Part 1 [Video]. YouTube. https://www.youtube.com/watch?v=njcVWdQEYXM
Shniqq. (z.d.). FastNoiseLite-Unity/CSharp/FastNoiseLite.cs at Master · Shniqq/FastNoiseLite-Unity. GitHub. https://github.com/shniqq/FastNoiseLite-Unity/blob/master/CSharp/FastNoiseLite.cs
Ramel, G. (2023, 29 september). Fish Locomotion & Movement 101: How Fish swim explained. Earth Life. https://earthlife.net/how-fish-swim-locomotion-movement/
