void Update()
 {
     if (chunkDataThreadInQueue.Count > 0)
     {
         for (int i = 0; i < chunkDataThreadInQueue.Count; i++)
         {
             MapThreadInfo <WorldChunkData> threadInfo = chunkDataThreadInQueue.Dequeue();
             threadInfo.callback(threadInfo.parameter);
         }
     }
     if (chunkComputedThreadInQueue.Count > 0)
     {
         for (int i = 0; i < chunkComputedThreadInQueue.Count; i++)
         {
             MapComputingThreadInfo <WorldChunkComputed> threadInfo = chunkComputedThreadInQueue.Dequeue();
             threadInfo.callback(threadInfo.parameter);
         }
     }
     if (chunkMeshThreadInQueue.Count > 0)
     {
         for (int i = 0; i < chunkMeshThreadInQueue.Count; i++)
         {
             MeshDataThreadInfo <MeshData> threadInfo = chunkMeshThreadInQueue.Dequeue();
             threadInfo.callback(threadInfo.parameter);
         }
     }
 }
    void Update()
    {
        // Process height map data
        if (heightMapDataThreadInfoQueue.Count > 0)
        {
            for (int i = 0; i < heightMapDataThreadInfoQueue.Count; i++)
            {
                HeightMapThreadInfo info = heightMapDataThreadInfoQueue.Dequeue();
                MeshGenerator.RequestMeshData(info.position, info.heightMap, levelOfDetail, OnTerrainMeshDataReceived, terrainColourGradient);
            }
        }

        // Process mesh data
        if (meshDataThreadInfoQueue.Count > 0)
        {
            for (int i = 0; i < meshDataThreadInfoQueue.Count; i++)
            {
                MeshDataThreadInfo info = meshDataThreadInfoQueue.Dequeue();

                GameObject chunk;
                if (info.type == MeshType.Water)
                {
                    chunk = CreateWater(info.position, info.meshData);
                }
                else
                {
                    chunk = CreateTerrainChunk(info.position, info.meshData);

                    if (createForest)
                    {
                        Vector3[]  normals          = chunk.GetComponent <MeshFilter>().sharedMesh.normals;
                        GameObject forestGameObject = CreateForest(info.heightMap, normals);
                        forestGameObject.transform.parent        = terrainChunks[info.position].transform;
                        forestGameObject.transform.localPosition = new Vector3(0f, 0f, forestGameObject.transform.position.z);
                    }
                }

                chunk.transform.parent        = terrainChunks[info.position].transform;
                chunk.transform.localPosition = new Vector3(0f, 0f, chunk.transform.position.z);
            }
        }

        if (viewer == null)
        {
            return;
        }

        Vector2 position = new Vector2(viewer.transform.position.x, viewer.transform.position.z);

        // Only show Terrain Chunks in range of viewer
        foreach (KeyValuePair <Vector2, GameObject> chunkEntry in terrainChunks)
        {
            GameObject chunk         = chunkEntry.Value;
            Vector2    chunkPosition = new Vector2(chunk.transform.position.x, chunk.transform.position.z);

            if ((position - chunkPosition).magnitude < chunkViewRange)
            {
                chunk.SetActive(true);
            }
            else
            {
                chunk.SetActive(false);
            }
        }
    }