How can I generate procedural 3D geometry faster?

In my game I have 3D grids that are generated then the y positions of the vertices are displaced to perlin noise, which makes terrain which has to be loaded in chunks. Currently I have the grid loading in chunks, the player can go in every direction infinitely and the way I do this is by removing the 3 chunks behind you and instantiating 3 chunks in front of you. This would be ok, if it didn’t take ten seconds to make the 3 chunks in front of you. How can I generate the chunks faster? I have experimented with not using perlin noise, which I thought was what was making it slow, but it didn’t make a difference. Here’s my code for generating the chunk, which are instantiated in another script. (well, its not really my code)

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class MeshTerrain : MonoBehaviour {

	public int sizeOfChunk = 128;
	private int size;
	private int length;
	public float spacing = 1;
	public MeshFilter terrainMesh = null;

	public int eMid = 2;
	public int sMid = 5;
	public int eHigh = 5;
	public int sHigh = 10;
	public int eLow = 1;
	public int sLow = 5;
	public int eMacro = 2;

	public int eTemp = 10;
	public int sTemp = 2;
	static int tempRandomiser = Random.Range (0,10000);

	public int ePrecip = 10;
	public int sPrecip = 2;
	static int precipRandomiser = Random.Range (0,10000);

	static int randomiser = Random.Range(0,10000);

	// Use this for initialization
	void Start () {
		size = sizeOfChunk + 3;

		if (terrainMesh == null)
		{
			Debug.LogError("ProceduralTerrain requires its target terrainMesh to be assigned.");
		}
		GenerateMesh();
	}
	
	// Update is called once per frame
	void Update () {
	
	}

	//this part generate terrain
	float GetHeight (float x, float z){
		float height;
		float heightA = Noise.Noise.GetNoise((x+transform.position.x) / sMid + randomiser,0, (z+transform.position.z) / sMid + randomiser) * -eMid;
		float heightB = Noise.Noise.GetNoise((x+transform.position.x) / sHigh + randomiser,0, (z+transform.position.z) / sHigh + randomiser) * -eHigh;
		float heightC = Noise.Noise.GetNoise((x+transform.position.x) / sLow + randomiser,0, (z+transform.position.z) / sLow + randomiser) * -eLow;

		float heightM = Noise.Noise.GetNoise((x+transform.position.x)  + randomiser,0, (z+transform.position.z)  + randomiser) * -eMacro +800;

		//float temperature = Noise.Noise.GetNoise((x+transform.position.x)/1.2f+ tempRandomiser,0, (z+ transform.position.z)/1.2f + tempRandomiser) * eTemp;
		//float precipitation = Noise.Noise.GetNoise((x+transform.position.x)/1.2f+ precipRandomiser,0, (z+ transform.position.z)/1.2f + precipRandomiser) * ePrecip;
		height = heightA + heightB + heightC + heightM;
		//Debug.Log (precipitation);
		//if(precipitation >= 10 && temperature <= 10){
		//	height -= 10;
		//}
		return height;
	}

	void GenerateMesh ()
	{
		List<Vector3[]> verts = new List<Vector3[]>();
		List<int> tris = new List<int>();
		List<Vector2> uvs = new List<Vector2>();

		for (int z = 0; z < size; z++)
		{
			verts.Add(new Vector3[size+1]);
			for (int x = 0; x < size; x++)
			{
				Vector3 current_point = new Vector3();
				current_point.x = (x * spacing);
				current_point.z = z * spacing;
				
				current_point.y = GetHeight(current_point.x-1, current_point.z);
				
				verts[z][x] = current_point;
				//uvs.Add(new Vector2(x,z)); 
				if (x-1 <= 0 || z <= 0 || x >= size)
				{
					continue;
				}
				// Generate the triangle north of you.
				tris.Add(x + z*size);
				tris.Add(x + (z-1)*size);
				tris.Add((x-1) + (z-1)*size);
				tris.Add((x-1) + z*size);
				tris.Add(x + z*size);
				tris.Add((x-1) + (z-1)*size);
			}
			
			// Unfold the 2d array of verticies into a 1d array.
			Vector3[] unfolded_verts = new Vector3[size*size];
			int i = 0;
			foreach (Vector3[] v in verts)
			{
				v.CopyTo(unfolded_verts, i * size);
				i++;
			}
			
			// Generate the mesh object.
			Mesh ret = new Mesh();
			ret.vertices = unfolded_verts;
			ret.triangles = tris.ToArray();
			//ret.uv = uvs.ToArray();
			
			// Assign the mesh object and update it.
			ret.RecalculateBounds();
			ret.RecalculateNormals();
			terrainMesh.mesh = ret;

		}
	}

}

So, how can I make this faster? Is there something here which is slowing down the game or do I need to try a different method?

Have you established what’s actually being done in that 10 seconds? Could you not do this constantly so you’re streaming a single line of verts/tri’s rather than doing entire blocks of terrain at once. The overhead might be considerably less.

Give the built-in profiler a try to speed up your code. Unity - Manual: The Profiler window

For example, use Profiler.BeginSample and Profiler.EndSample to mark sections of your code and see how much time is being spent in each section.

void Update() {
  for (int i=0; i<count; i++) {
     Profiler.BeginSample("Section 1");
     SomeFunction();
     Profiler.EndSample();
     Profiler.BeginSample("Section 2");
     AnotherFunction();
     Profiler.EndSample();
  }
}

The profiler will tell you about the time used in the different sections. Start with the section that takes the longest time and try to optimize that first.