Cube World Terrain generation

ive have been working on a voxel game, and have decided to tackle word generation using perlin noise, i managed to create simple terrain easily107010-my-terrain.png

but i wanted to create more interesting cube world sytled terrain
like this

ive been trying for 2 hours and have made no progress (and yes i have seen all the other posts)
so i decided to ask the internet

Heres the code i used to create the simple terrain

void Start () {
		float posX = transform.position.x;
		float posZ = transform.position.z;
		for (int y = 0; y < chunkY; y++) {

			for (int z = 0; z < chunkZ; z++) {
			
				for (int x = 0; x < chunkX; x++) {
					//Terrain algorithm
					float flatNoise =  Mathf.Round (Mathf.PerlinNoise ((transform.position.x + x) * Flatscale, (transform.position.z + z) * Flatscale ) * 10);
					float height = flatNoise;

					Vector3 pos = new Vector3 (posX, height, posZ);			
					GameObject newBlock = Instantiate (block, pos, Quaternion.identity) as GameObject;
					newBlock.transform.parent = this.transform;
					posX += 1;
				}
				posX = transform.position.x;
				posZ += 1;
			}
			posX = transform.position.x;
			posZ = transform.position.z;
		}
	}

Note: chunk x, y and z are just sizes

The main issue here is that you are using a 2D Noise function to generate 3D data, which causes all your blocks with the same x/z coordinate to spawn at the same y position. But let me complement this;


First off, you really got to understand how voxel data is managed. You could easily describe a voxel as the three dimensional pendant to a pixel.


When working with heightmaps (=pixel data), your height is stored in a two dimensional surface, (most likely a heightmap texture) where you can recieve an Y value for each two dimensional X/Z coordinate on your map.


Voxels though are stored in a three dimensional grid, or a so called volume, where each X/Y/Z index has his own value. For simplicity let’s say this could be a boolean, so your volume data would be something like:

bool[,,] volume = new bool[chunkX, chunkY, chunkZ];

You can fill that data using a 3D Noise function. I found this implementation of simplex noise earlier, maybe it can help you.


Then the next step would be to iterate over the volumes x,y,z indices, as you are actually doing allready. Recieve the data of the current block by simply reading the value from your volume and then spawn a block if the value is ‘true’:

bool spawnBlock = volume[x, y, z];

if (spawnBlock) {
    Vector3 pos = new Vector3 (x, y, z) * blockScale; 

    // spawn code here ...
}

EDIT: Allright @Remy_Unity was quicker :smiley: I suggest you to look at both answers since his shows you how to map a heightmap onto a voxel grid correctly and mine shows you how to generate the 3d noise shapes that produce caves and overhangs. If you combine both, you’ll get a good looking basic voxel terrain :slight_smile:

The issue is that your code is only using the 2D noise to generate height data.
To have more complex terrain like one you give as exemple, you will need to use 3D noise generation to create “density” data.

And with this you should then be able to generate the cubes.

To simplify the idea : instead of cube.pos.y = noise(x, z) do : if (noise(x,y,z) > 0.5) placeCube .

There is no 3D perlin in Unity, but you can hack it with Mathf.PerlinNoise(x, Mathf.PerlinNoise(y, z))