I have what I think is an off-by-one error in my mesh generation code but can seem to find it after staring at it for hours. The function is below and I've attached the _HeightMapPreview texture and a screen-shot of the issue. The _mapSize is 512. The issue is there is a gap between each block of the terrain. I'm hoping another set of eyes (or a few sets) will help. Edit: The Heightmap has an alpha channel so it looks blank. Code (csharp): public void BuildMesh() { GameObject oTerrain = new GameObject(); oTerrain.name = "Terrain"; float meshSize = 200f; if (_mapSize == 256) meshSize = 400; if (_mapSize == 512) meshSize = 800; int blocks = (int) Mathf.Ceil(_mapSize / 128f); int partsPerBlock = (int)Mathf.Ceil(_mapSize / blocks); Debug.Log("Map Size: " + _mapSize.ToString()); Debug.Log("Blocks: " + blocks.ToString()); Debug.Log("Parts Per Block: " + partsPerBlock.ToString()); for (int i = 0; i < blocks; i++) { for (int j = 0; j < blocks; j++) { GameObject oBlock = new GameObject(); oBlock.name = "Block " + (j*blocks + i).ToString(); oBlock.transform.parent = oTerrain.transform; oBlock.AddComponent<MeshFilter>(); oBlock.AddComponent<MeshRenderer>(); Mesh oMesh = oBlock.GetComponent<MeshFilter>().sharedMesh; if(oMesh == null) oMesh = new Mesh(); Vector3[] vertices = new Vector3[partsPerBlock * partsPerBlock]; Vector2[] uv = new Vector2[partsPerBlock * partsPerBlock]; Vector4[] tangents = new Vector4[partsPerBlock * partsPerBlock]; Vector2 uvScale = new Vector2 (1.0f / (_mapSize - 1), 1.0f / (_mapSize - 1)); Vector3 sizeScale = new Vector3(meshSize / (_mapSize - 1), 50f, meshSize / (_mapSize - 1)); int startX = partsPerBlock * i; if (startX < 0) startX = 0; int endX = startX + partsPerBlock; if (endX > _mapSize) endX = _mapSize; int startY = partsPerBlock * j; if (startY < 0) startY = 0; int endY = startY + partsPerBlock; if (endY > _mapSize) endY = _mapSize; for (int x = startX; x < endX; x++) { for (int y = startY; y < endY; y++) { int posX = x - startX; int posY = y - startY; //Debug.Log("["+posX.ToString()+", "+posY.ToString()+"] - "+(posY * partsPerBlock + posX).ToString() + " - "+vertices.Length.ToString()); float h = _HeightMapPreview.GetPixel(x,y).r +_HeightMapPreview.GetPixel(x,y).g + _HeightMapPreview.GetPixel(x,y).b + _HeightMapPreview.GetPixel(x,y).a; Vector3 vertex = new Vector3(x, h, y); vertices[posY * partsPerBlock + posX] = Vector3.Scale(sizeScale, vertex); uv[posY * partsPerBlock + posX] = Vector2.Scale(new Vector2 (x, y), uvScale); // Calculate tangent vector: a vector that goes from previous vertex // to next along X direction. We need tangents if we intend to // use bumpmap shaders on the mesh. h = _HeightMapPreview.GetPixel(x-1,y).r +_HeightMapPreview.GetPixel(x-1,y).g + _HeightMapPreview.GetPixel(x-1,y).b + _HeightMapPreview.GetPixel(x-1,y).a; Vector3 vertexL = new Vector3(x - 1, h, y); h = _HeightMapPreview.GetPixel(x+1,y).r +_HeightMapPreview.GetPixel(x+1,y).g + _HeightMapPreview.GetPixel(x+1,y).b + _HeightMapPreview.GetPixel(x+1,y).a; Vector3 vertexR = new Vector3(x + 1, h, y); Vector3 tan = Vector3.Scale(sizeScale, vertexR - vertexL).normalized; tangents[posY * partsPerBlock + posX] = new Vector4(tan.x, tan.y, tan.z, -1.0f); } } // Assign them to the mesh oMesh.vertices = vertices; oMesh.uv = uv; // Build triangle indices: 3 indices into vertex array for each triangle int[] triangles = new int[(partsPerBlock) * (partsPerBlock) * 6]; int index = 0; for (int y = startY; y < endY - 1; y++) { for (int x = startX; x < endX - 1; x++) { int posX = x - startX; int posY = y - startY; // For each grid cell output two triangles triangles[index++] = (posY * partsPerBlock) + posX; triangles[index++] = ((posY+1) * partsPerBlock) + posX; triangles[index++] = (posY * partsPerBlock) + posX + 1; triangles[index++] = ((posY+1) * partsPerBlock) + posX; triangles[index++] = ((posY+1) * partsPerBlock) + posX + 1; triangles[index++] = (posY * partsPerBlock) + posX + 1; } } // And assign them to the mesh oMesh.triangles = triangles; // Auto-calculate vertex normals from the mesh oMesh.RecalculateNormals(); // Assign tangents after recalculating normals oMesh.tangents = tangents; oBlock.GetComponent<MeshFilter>().sharedMesh = oMesh; } } }