Skip to content

Commit

Permalink
Update README.md
Browse files Browse the repository at this point in the history
  • Loading branch information
AK-Saigyouji authored Aug 17, 2016
1 parent 95c62e5 commit 3c2bb7c
Showing 1 changed file with 5 additions and 4 deletions.
9 changes: 5 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

## 0. Introduction

This is a set of scripts that allow the creation of 3D cave terrain in Unity with collision detection and full texture support. Once configured in the editor, caves can be generated with the click of a button.
This is a set of scripts that allow the creation of randomized 3D cave terrain in Unity with collision detection and full texture support. Once configured in the editor, caves can be generated with the click of a button. Features that can be configured include length and width, density, height, boundary size, scale, and heightmaps.

![3D cave with height map](http://i.imgur.com/sBi6T2U.jpg)

Expand All @@ -14,19 +14,19 @@ Note: The textures themselves are from an excellent free asset pack called [Natu

### In editor

Create a new empty game object, and attach one of the cave generator scripts: CaveGeneratorIsometric, or CaveGeneratorEnclosed. Configure the parameters as desired in the inspector (tooltips have been implemented to give additional information on what each parameter does). Then run the scene, and you will see two buttons appear in the inspector to generate a new map or to create a prefab. Generating a new map will create a new cave, and attach it as a child to the empty game object, overwriting any previously generated cave. Creating a prefab will turn the current cave into a prefab and save it into your directory in a folder called "GeneratedCave" along with the meshes. This allows you to exit play mode, drag the cave into your scene, and work with it in the editor.
Create a new empty game object, and attach one of the cave generator scripts: CaveGeneratorIsometric, or CaveGeneratorEnclosed. Configure the parameters as desired in the inspector (tooltips have been implemented to give additional information on what each parameter does). Run the scene, and you will see two buttons appear in the inspector: Generate New Map and Create Prefab. Generating a new map will create a new cave, and attach it as a child to the empty game object, overwriting any previously generated cave. Creating a prefab will convert the current cave into a prefab and save it into your directory in a folder called "GeneratedCave" along with the meshes. This allows you to exit play mode, drag the cave into your scene, and work with it in the editor.

### In code

You can also create caves entirely through code. Add the CaveGenerator namespace to your script, and use AddComponent to attach the cave generator to an object. Assign its parameters through the exposed properties. The GenerateCave method will then produce your cave just as the inspector button did. You can access the generated cave as a gameobject by using the ExtractCave method. Additionally, the Map property gives you access to a Grid object that can be indexed like a 2d array, and tells you whether a coordinate holds a wall or floor. This can be used to dynamically place content based on the resulting cave. Producing content this way is challenging, however, as everything has to be generated and placed programmatically.
You can also create caves entirely through code. Add the CaveGenerator namespace to your script, and use AddComponent to attach the cave generator to an object. Assign its parameters through the exposed properties. The GenerateCave method will then produce your cave just as the inspector button did. You can access the generated cave as a gameobject by using the ExtractCave method. Additionally, the Map property gives you access to a Grid object that can be indexed like a 2d array, and tells you whether a coordinate holds a wall or floor. This can be used to dynamically place content based on the resulting cave. Producing content this way is challenging, however, as everything has to be generated and placed programmatically. In the future I intend to offer substantially more support for pure dynamic generation of content.

### Using height maps

The other two attachable scripts provided are for varying the height in the terrain. HeightMapFloor will offer variation in the height of the floor, and HeightMapMain depends on what type of cave you're generating, but will affect the raised part of the terrain (the ceiling mesh for CaveGeneratorIsometric, and the enclosure mesh for CaveGeneratorEnclosed). Given that the parameters are a bit difficult to understand, height maps have a "Visualize" feature that allows you to see what the resulting floor or ceiling would look like in the scene. When enabled, it will draw a simple mesh that automatically updates in response to changes in the parameters. Play around with it until you get the height map you want.

## 2. Brief overview of how the generator works

This section contains some technical information for those curious how things work under the hood. An abstract class CaveGenerator drives the entire generator. It makes use of two major subsystems: map generation and mesh generation. Map generation produces a grid of tiles (under the hood, 0s and 1s) corresponding to floors and walls. This map is chopped up into chunks, and each chunk is sent to the mesh generator to be turned into meshes.
This section contains some technical information for those curious how things work under the hood. An abstract class CaveGenerator drives the entire generator. It makes use of two major subsystems: map generation and mesh generation. Map generation produces a grid of tiles (under the hood, 0s and 1s) corresponding to floors and walls. This map is chopped up into chunks, and each chunk is sent to MeshGenerator to be turned into meshes. MeshGenerator in turn delegates the low level details to various MeshBuilder classes, which are each responsible for component of the cave (floor, ceiling, wall, etc.)

The entire algorithm is asynchronous. Map generation is done on a background thread. Mesh generation is separated into a part that doesn't touch the API (background threads cannot touch the Unity API) and the part that does. The part that doesn't is distributed across multiple threads. Unity coroutines are used to deal with the part that does.

Expand All @@ -50,6 +50,7 @@ Marching squares is trivially parallelizable, so the majority of the mesh genera
* It is now possible to convert maps into prefabs with the press of a button, allowing content to be placed in the editor. This eliminates the need to generate all game content dynamically, a difficult task for more complicated games. This also makes it easier to use Unity's lighting and navigation features.
* The original project broke for maps much larger than 200 by 200, due to Unity's built in limitations on the number of vertices permitted in a single mesh. To fix this, the meshes are now generated in chunks, allowing for the creation of arbitrarily large maps. Additionally, the chunks can be dynamically toggled on/off during runtime so that only nearby chunks are rendered, significantly improving performance.
* Assigned uvs to the wall mesh, allowing textures to be applied.
* Assigned tangents to all meshes, supporting advanced shader features.
* Eliminated seams in the wall by sharing vertices rather than doubling up. This dramatically improves appearance of textures and lighting on walls.
* Created a custom inspector permitting map creation with the press of a button in the inspector.
* Fixed a bug with the smoothing function. In the original project, smoothing was done in place. This meant once a cell is changed, this change affected its neighbors when it's their turn. By copying changes into a new map, this issue is avoided.
Expand Down

0 comments on commit 3c2bb7c

Please sign in to comment.