public class ChunkReader : MonoBehaviour
{
public int chunk_width = 128;
public int chunk_height = 64;

public int map_width = 2048;
public int map_height = 1024;

public Texture2D HeightMap;

private int chunk_count = 0;

//private int CurXChunk, CurYChunk; //Which chunk are we parsing?
private void Start()
{
}
{
for(int i = 0; i < map_width; i+=chunk_width)
{
for(int j = 0; j < map_width; j+=chunk_height)
{
}
}
}

{
List<Vector3> verts = new List<Vector3>();
List<int> tris = new List<int>();

//Bottom left section of the map, other sections are similar
for (int i = chunk_x; i < chunk_width; i++)
{
for (int j = chunk_y; j < chunk_height; j++)
{
//Add each new vertex in the plane
verts.Add(new Vector3(i, HeightMap.GetPixel(i, j).grayscale * 100, j));
//Skip if a new square on the plane hasn't been formed
if (i == 0 || j == 0) continue;
//Adds the index of the three vertices in order to make up each of the two tris
tris.Add(chunk_height * i + j); //Top right
tris.Add(chunk_height * i + j - 1); //Bottom right
tris.Add(chunk_height * (i - 1) + j - 1); //Bottom left - First triangle
tris.Add(chunk_height * (i - 1) + j - 1); //Bottom left
tris.Add(chunk_height * (i - 1) + j); //Top left
tris.Add(chunk_height * i + j); //Top right - Second triangle
}
}

Vector2[] uvs = new Vector2[verts.Count];
for (var i = 0; i < uvs.Length; i++) //Give UV coords X,Z world coords
uvs[i] = new Vector2(verts[i].x, verts[i].z);

GameObject plane = new GameObject("Chunk  " + chunk_count); //Create GO and add necessary components
chunk_count++;
Mesh procMesh = new Mesh();
procMesh.vertices = verts.ToArray(); //Assign verts, uvs, and tris to the mesh
procMesh.uv = uvs;
procMesh.triangles = tris.ToArray();
procMesh.RecalculateNormals(); //Determines which way the triangles are facing
plane.GetComponent<MeshFilter>().mesh = procMesh; //Assign Mesh object to MeshFilter
}
// Update is called once per frame
void Update()
{

}
}


Basically, I'm trying to load a map into my game using Unity3D using the above code and the below-linked heightmap, but only the first chunk (at 0,0) actually loads, and the rest don't render for whatever reason. I really don't understand what I'm doing wrong. Probably super basic.

As you can see below, Chunk 0 generates fine, but all concurrent chunks generate with no functional mesh and at the exact same location.

There are a couple of issues with your algorithm:

First, in LoadChunks, you use the same boundary for both of your loops (map_width). This wouldn't be an issue if your map were square. The line

for(int j = 0; j < map_width; j+=chunk_height)


should be

for(int j = 0; j < map_height; j+=chunk_height)


This is not the cause of having only the first chunk generate. The reason why only the first chunk generates is that there is an issue in the loops boundaries in the LoadChunk function.

for (int i = chunk_x; i < chunk_width; i++)
{
for (int j = chunk_y; j < chunk_height; j++)
{


This will work for the first chunk, but when you get to the other ones, chunk_x or chunk_y will necessarily be greater-or-equal than-to chunk_width or chunk_height because they were the upper-bound of the previous run.

Some parts of the inner loop appear to expect the indices i and j to be in the range [0..chunk_size), while some other parts expect them to be in the range [0..map_size).

To make the code a bit easier to read, I suggest you stick with the concept of [0..chunk_size):

for (int i = 0; i < chunk_width; i++)
{
for (int j = 0; j < chunk_height; j++)
{
int world_index_x = chunk_x + i;
int world_index_y = chunk_y + j;
verts.Add(new Vector3(world_index_x, HeightMap.GetPixel(world_index_x, world_index_y).grayscale * 100, world_index_y));


The final code should be something like this:

public class ChunkReader : MonoBehaviour
{
public int chunk_width = 128;
public int chunk_height = 64;

public int map_width = 2048;
public int map_height = 1024;

public Texture2D HeightMap;

private int chunk_count = 0;

//private int CurXChunk, CurYChunk; //Which chunk are we parsing?
private void Start()
{
}
{
for(int i = 0; i < map_width; i+=chunk_width)
{
for(int j = 0; j < map_height; j+=chunk_height)
{
}
}
}

{
List<Vector3> verts = new List<Vector3>();
List<int> tris = new List<int>();

//Bottom left section of the map, other sections are similar
for (int i = 0; i < chunk_width; i++)
{
for (int j = 0; j < chunk_height; j++)
{
//Add each new vertex in the plane
int world_index_x = chunk_x + i;
int world_index_y = chunk_y + j;
verts.Add(new Vector3(world_index_x, HeightMap.GetPixel(world_index_x, world_index_y).grayscale * 100, world_index_y));
//Skip if a new square on the plane hasn't been formed
if (i == 0 || j == 0) continue;
//Adds the index of the three vertices in order to make up each of the two tris
tris.Add(chunk_height * i + j); //Top right
tris.Add(chunk_height * i + j - 1); //Bottom right
tris.Add(chunk_height * (i - 1) + j - 1); //Bottom left - First triangle
tris.Add(chunk_height * (i - 1) + j - 1); //Bottom left
tris.Add(chunk_height * (i - 1) + j); //Top left
tris.Add(chunk_height * i + j); //Top right - Second triangle
}
}

Vector2[] uvs = new Vector2[verts.Count];
for (var i = 0; i < uvs.Length; i++) //Give UV coords X,Z world coords
uvs[i] = new Vector2(verts[i].x, verts[i].z);

GameObject plane = new GameObject("Chunk  " + chunk_count); //Create GO and add necessary components
chunk_count++;
Mesh procMesh = new Mesh();
procMesh.vertices = verts.ToArray(); //Assign verts, uvs, and tris to the mesh
procMesh.uv = uvs;
procMesh.triangles = tris.ToArray();
procMesh.RecalculateNormals(); //Determines which way the triangles are facing
plane.GetComponent<MeshFilter>().mesh = procMesh; //Assign Mesh object to MeshFilter
}
// Update is called once per frame
void Update()
{

}
}