I'm in the beginning stages of an RTS game in Unity. I have a procedurally generated terrain with a Perlin noise height map, as well as a function to generate a river. The problem is that the graphical creation of the map is taking the data structure of the map and rotating it by 180 degrees.
I noticed this problem when I was creating my rivers. I would set the river's height to flat, and noticed that the actual tiles that were flat in the graphical representation were flipped and mirrored.
Here are some screenshots of the map from different angles:
As you can see, if you flipped (graphically) the river by 180 degrees on the Z axis, it would fit where the terrain is flattened. I have a suspicion it is being caused by a misunderstanding on my part of how vertices work.
This code here creates a new array of Tile
objects, which hold the information for each tile, including its type, coordinate, height, and it's vertices:
public DTileMap (int size_x, int size_y)
{
this.size_x = size_x;
this.size_y = size_y;
//Initialize Map_Data Array of Tile Objects
map_data = new Tile[size_x, size_y];
for (int j = 0; j < size_y; j++) {
for (int i = 0; i < size_x; i++) {
map_data [i, j] = new Tile ();
map_data[i,j].coordinate.x = (int)i;
map_data[i,j].coordinate.y = (int)j;
map_data[i,j].vertices[0] = new Vector3 (i * GTileMap.TileMap.tileSize, map_data[i,j].Height, -j * GTileMap.TileMap.tileSize);
map_data[i,j].vertices[1] = new Vector3 ((i+1) * GTileMap.TileMap.tileSize, map_data[i,j].Height, -(j) * GTileMap.TileMap.tileSize);
map_data[i,j].vertices[2] = new Vector3 (i * GTileMap.TileMap.tileSize, map_data[i,j].Height, -(j-1) * GTileMap.TileMap.tileSize);
map_data[i,j].vertices[3] = new Vector3 ((i+1) * GTileMap.TileMap.tileSize, map_data[i,j].Height, -(j-1) * GTileMap.TileMap.tileSize);
}
}
}
This code sets the river tiles to height 0:
foreach (Tile t in map_data)
{
if (t.realType == "Water")
{
t.vertices[0].y = 0f;
t.vertices[1].y = 0f;
t.vertices[2].y = 0f;
t.vertices[3].y = 0f;
}
}
Finally, below is the code to generate the actual graphics from the data:
public void BuildMesh ()
{
DTileMap.DTileMap map = new DTileMap.DTileMap (size_x, size_z);
int numTiles = size_x * size_z;
int numTris = numTiles * 2;
int vsize_x = size_x + 1;
int vsize_z = size_z + 1;
int numVerts = vsize_x * vsize_z;
// Generate the mesh data
Vector3[] vertices = new Vector3[ numVerts ];
Vector3[] normals = new Vector3[numVerts];
Vector2[] uv = new Vector2[numVerts];
int[] triangles = new int[ numTris * 3 ];
int x, z;
for (z=0; z < vsize_z; z++) {
for (x=0; x < vsize_x; x++) {
normals [z * vsize_x + x] = Vector3.up;
uv [z * vsize_x + x] = new Vector2 ((float)x / size_x, 1f - (float)z / size_z);
}
}
for (z=0; z < vsize_z; z+=1) {
for (x=0; x < vsize_x; x+=1) {
if (x == vsize_x - 1 && z == vsize_z - 1) {
vertices [z * vsize_x + x] = DTileMap.DTileMap.map_data [x - 1, z - 1].vertices [3];
} else if (z == vsize_z - 1) {
vertices [z * vsize_x + x] = DTileMap.DTileMap.map_data [x, z - 1].vertices [2];
} else if (x == vsize_x - 1) {
vertices [z * vsize_x + x] = DTileMap.DTileMap.map_data [x - 1, z].vertices [1];
} else {
vertices [z * vsize_x + x] = DTileMap.DTileMap.map_data [x, z].vertices [0];
vertices [z * vsize_x + x+1] = DTileMap.DTileMap.map_data [x, z].vertices [1];
vertices [(z+1) * vsize_x + x] = DTileMap.DTileMap.map_data [x, z].vertices [2];
vertices [(z+1) * vsize_x + x+1] = DTileMap.DTileMap.map_data [x, z].vertices [3];
}
}
}
for (z=0; z < size_z; z++) {
for (x=0; x < size_x; x++) {
int squareIndex = z * size_x + x;
int triOffset = squareIndex * 6;
triangles [triOffset + 0] = z * vsize_x + x + 0;
triangles [triOffset + 2] = z * vsize_x + x + vsize_x + 0;
triangles [triOffset + 1] = z * vsize_x + x + vsize_x + 1;
triangles [triOffset + 3] = z * vsize_x + x + 0;
triangles [triOffset + 5] = z * vsize_x + x + vsize_x + 1;
triangles [triOffset + 4] = z * vsize_x + x + 1;
}
}
// Create a new Mesh and populate with the data
Mesh mesh = new Mesh ();
mesh.vertices = vertices;
mesh.triangles = triangles;
mesh.normals = normals;
mesh.uv = uv;
// Assign our mesh to our filter/renderer/collider
MeshFilter mesh_filter = GetComponent<MeshFilter> ();
MeshCollider mesh_collider = GetComponent<MeshCollider> ();
mesh_filter.mesh = mesh;
mesh_collider.sharedMesh = mesh;
calculateMeshTangents (mesh);
BuildTexture (map);
}