/// <summary>
    /// <para>Notify the chunk loading. If is a parallel execution, is added to the ChunksLoaded list in order to be build at BuildParallelyLoadedChunks method.</para>
    /// <para>If the chunk is for map, it is added to ChunksForMap list.</para>
    /// <para>Otherwise, the chunk is build.</para>
    /// <para>IMPORTANT: If is a parallel execution, this method can't instanciate any child of GameObject.</para>
    /// </summary>
    /// <param name="chunk">Chunk instance.</param>
    /// <param name="isParellel">If the chunk is loading in parallel.</param>
    /// <param name="isForMap">If the chunk is loading for the terrain mapping.</param>
    protected virtual void ChunkLoaded(Chunk chunk, bool isParallel, bool isForMap)
    {
        if (isParallel)
        {
            Monitor.Enter(ChunksLoadingLock);
        }

        if (isForMap)
        {
            ChunksLoadingForMap.Remove(chunk.Position);
            ChunksForMap.Add(chunk.Position, chunk);
        }
        else if (isParallel)
        {
            ChunksLoading.Remove(chunk.Position);
            ChunksLoaded.Add(chunk.Position, chunk);
        }

        if (isParallel)
        {
            Monitor.Exit(ChunksLoadingLock);
        }
        else if (!isForMap)
        {
            BuildChunk(chunk);
            CurrentChunks.Add(chunk.Position, chunk);
        }
    }
    /// <summary>
    /// Builds the chunks loaded parallely. For each chunk it uses the InMaxUpdateTime method, breaking the loop if the MaxUpdateTime is exceeded.
    /// </summary>
    protected virtual void BuildParallelyLoadedChunks()
    {
        if (ChunksLoaded.Count > 0)
        {
            lock ( ChunksLoadingLock )
            {
                Chunk             chunk;
                List <Vector2Int> chunksBuilt          = new List <Vector2Int>(ChunksLoaded.Count);
                float             loopStartTime        = Time.realtimeSinceStartup;
                float             numIterations        = 0;
                float             averageIterationTime = 0;
                foreach (KeyValuePair <Vector2Int, Chunk> entry in ChunksLoaded)
                {
                    if (InMaxUpdateTime(averageIterationTime))
                    {
                        chunk = entry.Value;
                        if (IsChunkRequired(chunk.Position))
                        {
                            BuildChunk(chunk);
                            CurrentChunks.Add(chunk.Position, chunk);
                        }
                        else
                        {
                            chunk.Destroy();
                        }

                        chunksBuilt.Add(entry.Key);

                        numIterations++;
                        averageIterationTime = (Time.realtimeSinceStartup - loopStartTime) / numIterations;
                    }
                    else
                    {
                        break;
                    }
                }

                // Delete chunks already built
                foreach (Vector2Int key in chunksBuilt)
                {
                    ChunksLoaded.Remove(key);
                }
            }
        }
    }