Procedural Terrain Generation Issues

Okay so basically I’ve been working on a survival game with procedural terrain generation. How can I render new chunks without causing performance issues? Thanks.

Chunk Manager

Purpose: Script used to render and hide chunks (Convert back to chunk data)
Issue: Misaligned with the rootpart position, I want it at the center.

local wait = task.wait
local delay = task.delay
local defer = task.defer

local players = game:GetService("Players")

local replicatedStorage = game:GetService("ReplicatedStorage")
local fold_modules = replicatedStorage:WaitForChild("Modules")
local mod_terrainManager = require(fold_modules:WaitForChild("TerrainManager"))

local chunkSize = 90/4

local function gridSnapNumber(x)
	return math.round(x/chunkSize)*chunkSize
end

local function gridSnapVector3(x)
	return Vector3.new(math.round(x.X/chunkSize)*chunkSize, math.round(x.Y/chunkSize)*chunkSize, math.round(x.Z/chunkSize)*chunkSize)
end

while wait(1) do
	for i, player in pairs(players:players()) do
		local character = player.Character
		
		if character then
			
			local root = character.PrimaryPart
			
			if root then
				local pos = gridSnapVector3(Vector3.new(root.Position.X, 0, root.Position.Z))
				
				for x = -10, 0 do
					for z = -10, 0 do
						local cpos = (pos + (Vector3.new(x, 0, z) * chunkSize)) - (Vector3.new(chunkSize, 0, chunkSize)*2)
						
						if not mod_terrainManager:getUnloadedChunk(cpos) then
							mod_terrainManager:newChunk(cpos)
							mod_terrainManager:GenerateChunk(cpos)
						end
					end
				end
			end
			
		end
	end
end

Chunk Data Generator

Purpose: Generating chunk data
Issue: Requires wait()

function terrainManager:newChunk(position, seed)
	if self:chunkExists(position) then return end
	
	local seed = seed
	
	local function getNoise(a, b)
		return math.noise(a, b, seed)
	end
	local chunk = {}
	chunk.voxels = {}

	local position = gridSnapVector3(position)

	self.unloadedChunks[position] = chunk
	chunks[position] = chunk
	
	for x = position.X, position.X + chunkSize do
		for z = position.Z, position.Z + chunkSize do
			
			local yNoise = (getNoise(x/180, z/180) * height)
			local top = position.Y - yNoise

			if top <= seaLevel then
				top = seaLevel
			end

			top = (math.floor(top)/4)*4
			
			for y = top - height, top, 4 do
				
				local newVoxel = {}

				local voxelCFrame = CFrame.new(x * 4, y, z * 4)
				local voxelSize = Vector3.new(4,4,4)
				local voxelMaterial = Enum.Material.Grass

				if y < -1 then
					voxelMaterial = Enum.Material.Sand
				end

				if top <= seaLevel then
					voxelMaterial = Enum.Material.Water
				end

				if y < top - height + 4 then
					voxelMaterial = Enum.Material.Ground
				end

				newVoxel.cframe = voxelCFrame
				newVoxel.size = voxelSize
				newVoxel.material = voxelMaterial

				chunk.voxels[newVoxel.cframe] = newVoxel

			end

		end

	end
end

Chunk Data Visualizer (Possible lag source)

Purpose: Convert chunk data into Terrain.
Issue: Possible lag source?

function terrainManager:GenerateChunk(position)
	local position = gridSnapVector3(position)
	
	local chunkData = self:getChunk(position)
	
	if chunkData.voxels then
		local iterations = 0
		
		for _, voxel in pairs(chunkData.voxels) do
			iterations += 1
			
			if iterations >= 8000 then
				iterations = 0
				wait()
			end
			
			workspace.Terrain:FillBlock(voxel.cframe, voxel.size, voxel.material or Enum.Material.Grass)
		end
	end
end

Might not be a complete fix, but do not load anything under the terrain as that takes up performance itself.
Else pre-loading it might be an easier fix.

Earlier today I set the maximum Y value to 1 and the lag disappeared. But, I don’t want it to be 4 studs thick.

If you want to make a mining game take inspiration from Mining Simulator - Roblox, basically what they do here is when you break a block more blocks around it appear. Basically you should do the same for terrain instead of parts.

But the chunk manager is a server sided thing. (For security reasons)

Look what I am saying is make the terrain thin and if you want to give the player ability to mine just take inspiration of the game Mining Simulator - Roblox, they dont load all the blocks at once.

Having too much terrain is the issue here so any way to fix it would work, else re-loading chunks every 5 seconds would work sort of, except you will have lag spikes.

I also get this strange error

What you can do is get the minimum Y and maximum Y around every area after that you want to either make the terrain thinner or thicker.

The problem is inside the Chunk Manager script, What I want it to do is generate chunks around the player. In a square manner. It doesn’t appear to be working, Wait hold on I just thought of something to maybe fix it.