Surface Blocks Only Visible Not Working

Hello, I am currently experimenting with terrain generation, and am trying to make it so only blocks that are exposed to “Air” are visible, allowing players to see only what is exposed to their view.

I had a problem while trying to check around the block, since some blocks seem to have been “skipped over”, or just that it didn’t detect an air block. I am wondering how my script just doesn’t function on some blocks, while it does on others.

Screenshot of attempt:


As you can see, there are parts of it missing, and I have no idea how that happens.

Script: (ModuleScript)

function GetBlockFromPosition(WorldBlocks,X,Y,Z)
	return WorldBlocks["Block"..X..Y..Z]
end

function module.CheckVisibleLayers(WorldBlocks)
	for i,Block in pairs(WorldBlocks) do
		for x = 1,3 do
			for z = 1,3 do
				for y = 1,3 do
					local TargetBlock = GetBlockFromPosition(WorldBlocks,Block.X + (x - 2),Block.Y + (y - 2),Block.Z + (y - 2))
					if TargetBlock then
						if TargetBlock.Name == "Air" then
							WorldBlocks[i].Visible = true
						end
					end
				end
			end
		end
	end
	return WorldBlocks
end

function module.UpdateBlocks(WorldBlocks)
	for i,v in pairs(workspace.Chunks:GetChildren()) do
		v:ClearAllChildren()
	end
	for i,Block in pairs(WorldBlocks) do
		if Block.Visible then
			local NewBlock = game.ServerStorage.Blocks:FindFirstChild(Block.Name)
			if NewBlock then
				NewBlock = NewBlock:Clone()
				NewBlock.Parent = workspace.Chunks["Chunk"..Block.ChunkX..Block.ChunkY..Block.ChunkZ]
				NewBlock:SetPrimaryPartCFrame(CFrame.new(Block.X*BlockSize,Block.Y*BlockSize,Block.Z*BlockSize))
			end
		end
	end
end

Thanks for reading!

Try this, I don’t know if it will work, its just a guess…

function GetBlockFromPosition(WorldBlocks,X,Y,Z)
	return WorldBlocks["Block"..X..Y..Z]
end

function module.CheckVisibleLayers(WorldBlocks)
	for i,Block in pairs(WorldBlocks) do
		for x = 1,3 do
			for z = 1,3 do
				for y = 1,3 do
					local TargetBlock = GetBlockFromPosition(WorldBlocks,Block.X ,Block.Y + (y - 2),Block.Z
					if TargetBlock then
						if TargetBlock.Name == "Air" then
							WorldBlocks[i].Visible = true
						end
					end
				end
			end
		end
	end
	return WorldBlocks
end

function module.UpdateBlocks(WorldBlocks)
	for i,v in pairs(workspace.Chunks:GetChildren()) do
		v:ClearAllChildren()
	end
	for i,Block in pairs(WorldBlocks) do
		if Block.Visible then
			local NewBlock = game.ServerStorage.Blocks:FindFirstChild(Block.Name)
			if NewBlock then
				NewBlock = NewBlock:Clone()
				NewBlock.Parent = workspace.Chunks["Chunk"..Block.ChunkX..Block.ChunkY..Block.ChunkZ]
				NewBlock:SetPrimaryPartCFrame(CFrame.new(Block.X*BlockSize,Block.Y*BlockSize,Block.Z*BlockSize))
			end
		end
	end
end

And if that doesn’t work, this is my second guess…

function GetBlockFromPosition(WorldBlocks,X,Y,Z)
	return WorldBlocks["Block"..X..Y..Z]
end

function module.CheckVisibleLayers(WorldBlocks)
	for i,Block in pairs(WorldBlocks) do
		for x = 1,3 do
			for z = 1,3 do
				for y = 1,3 do
					local TargetBlock = GetBlockFromPosition(WorldBlocks,Block.X,Block.Y,Block.Z)
					if TargetBlock then
						if TargetBlock.Name == "Air" then
							WorldBlocks[i].Visible = true
						end
					end
				end
			end
		end
	end
	return WorldBlocks
end

function module.UpdateBlocks(WorldBlocks)
	for i,v in pairs(workspace.Chunks:GetChildren()) do
		v:ClearAllChildren()
	end
	for i,Block in pairs(WorldBlocks) do
		if Block.Visible then
			local NewBlock = game.ServerStorage.Blocks:FindFirstChild(Block.Name)
			if NewBlock then
				NewBlock = NewBlock:Clone()
				NewBlock.Parent = workspace.Chunks["Chunk"..Block.ChunkX..Block.ChunkY..Block.ChunkZ]
				NewBlock:SetPrimaryPartCFrame(CFrame.new(Block.X*BlockSize,Block.Y*BlockSize,Block.Z*BlockSize))
			end
		end
	end
end

Again, this is just a guess, I don’t really know the environment the script is in, so this seems like the best solution to me.