Creating a map with floating islands - Kraddak/UnityStudy GitHub Wiki

A small disclaimer, random map generation was a concept never faced before. Therefore much of the contents of this section is really a study of the tutorial made by Sebastian League, and a very excellent one in my opinion. In this section I want to discuss how I built upon this generator, for creating a map of "islands" surrounded by the "void", with also ravines here and there. A possible mechanic here is to have units be pushed or pulled on ravines and fall to their doom.

Creating a height map with Perlin noise

We can populate a 2x2 array with height values with the Perlin noise function. We can also use the falloff generator to create terrain that is on the center, and have the borders "voided". We can visualize it then with black and white, having the black cells with low values, and grey and white cells with higher values. NoiseMap

Visualizing the map with a mesh

The next step would be to use a mesh, and use this relation: We have x and z as indexes for the matrix, and we could call the value contained in [x,z] as y, which is the height in position [x,z]. And therefore: a vertex is [a, b, c]. a = x c = z b = heightMap[x,z] (aka "y") Of course we need to define also the triangles. The code initially looked like this (slightly different to the final version):

public static MeshData GenerateTerrainMesh(float[,] heightMap, float voidHeight, float heightMultiplier, AnimationCurve heightCurve){
    int sizeX = heightMap.GetLength(0);
    int sizeZ = heightMap.GetLength(1);
    MeshData meshData = new MeshData(sizeX, sizeZ);

    int vertexIndex = 0;
    for (int x = 0; x < sizeX; x++){
        for (int z = 0; z < sizeZ; z++){

            if (heightMap[x, z] > voidHeight){
            Vector3 vertex = new Vector3(x, heightCurve.Evaluate(heightMap [x, z]) * heightMultiplier, z);
            meshData.vertices[vertexIndex] = vertex;
                // Set UV coordinates based on vertex position
                meshData.uvs[vertexIndex] = new Vector2((float)x / sizeX, (float)z / sizeZ);

                // Check neighboring vertices to create triangles
                if (x < sizeX - 1 && z < sizeZ - 1 && 
                    heightMap[x + 1, z] > voidHeight && 
                    heightMap[x, z + 1] > voidHeight && 
                    heightMap[x + 1, z + 1] > voidHeight)
                {
                    int a = vertexIndex;
                    int b = vertexIndex + sizeZ;
                    int c = vertexIndex + sizeZ + 1;
                    int d = vertexIndex + 1;
                    meshData.AddTriangle(a, c, b);
                    meshData.AddTriangle(c, a, d);
                }
            }

            vertexIndex++;
        }
    }

    return meshData;
}

The check heightMap[x, z] > voidHeight is here to ignore the lower values, and not add terrain but it's not enough. image


We need to act also on the noise map. I decided that -1 would be the "void" level/value, 0 the lowest altitude of the terrain, all else would go upper. I wanted also to have a square grid look for the map. We can now render all the lower values -1, and we now that the border vectors of the islands are all 0. image

The problem is that various values at the border of the islands are now to 0, and without any precautions, we end up creating creating this weird triangles. image

Look at the image below, it represent the noise map. The darker the values the higher the terrain. When creating the triangles, we could use only the red dots as a border, and ignore the green ones. Which is what we do in the final code. image image