Infinite Procedural generation problems

I am working on an infinitely generated universe and I ran into some problems so if anyone could tweak the code below to get it working properly, I would appreciate it. The problem with the code is that i’m getting this error attempt to index field ‘?’ (a nil value) on line 17.

local cameraPosition = Vector3.new(0,0,0)
local systemchoices = game.ServerStorage.Systems:GetChildren()

local systems = {}
local choices = {}

local function chunkExists(chunkX, chunkY, chunkZ)
	if not systems[chunkX] then
		systems[chunkX] = {}
	end
	if not systems[chunkY] then
		systems[chunkY] = {}
	end
	if not systems[chunkZ] then
		systems[chunkZ] = {}
	end
	return systems[chunkX][chunkY][chunkZ]
end

function makeChunk(x, y, z)
	local vector = Vector3.new(x, y, z)
	systems[x][y][z] = true
	for i=1,#systemchoices do
		if systemchoices[i]:isA("Model") then
			table.insert(choices,systemchoices[i])
		end
	end
	local picked = math.random(1,#systemchoices)
	local systemClone = game.ServerStorage.Systems:FindFirstChild(choices[picked].Name):Clone()
	systemClone.Parent = game.Workspace
	systemClone:MoveTo(vector)
end

function checkSurroundings(pos)
	local chunkX, chunkY, chunkZ = math.floor(pos.X / 3), math.floor(pos.Y / 3), math.floor(pos.Z / 3)
	local range = math.max(1, 100)
	for x = -range, range do
		for y = -range, range do
			for z = -range, range do
				local cx, cy, cz = chunkX + x
				local cy, cz = chunkY + y
				local  cz = chunkZ + z
				if not chunkExists(cx, cy, cz) then
					makeChunk(cx, cy, cz)
				end
			end
		end
	end
end

game.Workspace.cameraPos.OnServerEvent:Connect(function(player, pos)
	cameraPosition = pos
end)
 
game:GetService("RunService").Heartbeat:Connect(function()
	checkSurroundings(cameraPosition)
end)

I have used the code above for 2d infinite generation and it works fine but 3d gets more complicated and I have no idea how to fix it. I have tried a few solutions but none of them worked

3 Likes

Line 17:

return systems[chunkX][chunkY][chunkZ]

You’re indexing systems at key chunkX and then indexing that result at key chunkY and then indexing that result at key chunkZ.

One of those results is nil, but you attempt the next index anyway.

Add this to line 16 to figure out which is nil:

print ("systems",systems); print("chunkX", systems[chunkX]); print("chunkY", systems[chunkX][chunkY]); print("chunkZ",systems[chunkX][chunkY][chunkZ])

This will error as well. But we will see which ones printed. If none print, systems is nil. If only systems prints, chunkX is nil, and so on.

1 Like

the third print statement prints: ‘chunkY: nil’ but the last print statement does not print

I tried replacing the chunckExists function with the code below but when i try to test it the game never loads and it just displays timeout errors for random lines in the script.

local function chunkExists(chunkX, chunkY, chunkZ)
	if not systems[chunkX] then
		systems[chunkX] = {}
	end
	if not systems[chunkX][chunkY] then
		systems[chunkX][chunkY] = {}
	end
	if not systems[chunkX][chunkY][chunkZ] then
		systems[chunkX][chunkY][chunkZ] = {}
	end
	return systems[chunkX][chunkY][chunkZ]
end

Okay. This means that chunkY is nil, so it errors when you try to index it by chunkZ.

Your if statements don’t actually check the sections that you’ll be indexing.

local function chunkExists(chunkX, chunkY, chunkZ)
	if not systems[chunkX] then
		systems[chunkX] = {}
	end
	if not systems[chunkY] then
		systems[chunkY] = {}
	end
	if not systems[chunkZ] then
		systems[chunkZ] = {}
	end
	return systems[chunkX][chunkY][chunkZ]
end

It doesn’t matter if systems[chunkY] exists, since you’ll be indexing chunkY into systems[chunkX]!

Here’s a corrected version:

local function chunkExists(chunkX, chunkY, chunkZ)
	if not systems[chunkX] then
		systems[chunkX] = {}
	end
	if not systems[chunkX][chunkY] then
		systems[chunkX][chunkY] = {}
	end
	if not systems[chunkX][chunkY][chunkZ] then
		systems[chunkX][chunkY][chunkZ] = {}
	end
	return systems[chunkX][chunkY][chunkZ]
end

EDIT:

Nothing is random. Please elaborate!

1 Like

For some reason my revised code was the same as your revised code but when I copied yours it started working but it was very laggy and I was wondering if there was a way to only check for chunks at certain intervals like intervals of 10 or 20.