Generation system spawns tiles in the exact same place

  1. What do you want to achieve? Keep it simple and clear!
    I want to create a tile generation system. Tiles will be placed around other tiles if they don’t already exist. I have two seperate functions, createTile() and loadTile(). createTile() will add the tile to the data, while loadTile() will place down the phyiscal part.

  2. What is the issue? Include screenshots / videos if possible!

All tiles are in the exact same place.
Tiles

Part of the table from print(tiles)
Tiles2

Part of the table from print(tilesTaken)
Tiles3

  1. What solutions have you tried so far? Did you look for solutions on the Developer Hub?
    I can’t find something that will help on the Dev Hub.

My code: (Module script)

local generationManager = {}

local serverStorage = game:GetService("ServerStorage")
local objects = serverStorage.generation

local config = {
	seed = 1, --World randomseed
	floor = 50, --Studs of floor/tile size
	maximum = 20, --Maxiumum number of tiles
}

local tiles = {}
local tilesTaken = {}

math.randomseed(config.seed)

local function loadTile(data)
	local tile = Instance.new("Part")
	tile.Name = "Tile "..data.x..", "..data.y
	tile.Anchored = true
	tile.Size = Vector3.new(config.floor, 1, config.floor)
	tile.Position = Vector3.new(data.x * config.floor, -1, data.y * config.floor)
	
	local display = script.display:Clone()
	display.text.Text = data.text
	display.Parent = tile
	
	tile.Parent = game.Workspace.Tiles
end

local function createTile(data)
	if table.find(tilesTaken, {x = data.x, y = data.y}) or #tilesTaken > config.maximum then
		return
	end
	table.insert(tilesTaken, {x = data.x, y = data.y})
	tiles[#tiles + 1] = data
	
	for x = data.x - 1, data.x + 1 do
		for y = data.y - 1, data.y + 1 do
			local newData = data
			newData.x = x
			newData.y = y
			spawn(function()
				createTile(newData)
			end) 
		end
	end
end

spawn(function()
	game.Workspace.Important.Baseplate.Texture:Destroy()
	game.Workspace.Important.Baseplate.Transparency = 1

	for _, object in game.Workspace:GetChildren() do
		if table.find({"Folder", "Terrain", "Camera"}, object.ClassName) == nil then
			object:Destroy()
		end
		wait(0.0001)
	end
end)

createTile({x = 0, y = 0, text = "Hello"})

while #tilesTaken < config.maximum do
	wait(0.25)
	print(#tilesTaken / config.maximum)
end

print(tiles)
print(tilesTaken)

wait(0.1)
for _, tile in tiles do
	loadTile(tile)
	wait(0.01)
end

return generationManager
1 Like

I believe your use of tables is making your scripts behave poorly. Tables are passed and stored as references, meaning things like local newData = data isn’t making you a copy and you end up editing data unknowingly. table.find will never find duplicate tables since it’s checking the table’s reference not it’s values.

if table.find(tilesTaken, {x = data.x, y = data.y})

using {} will create a new table every time, which is never going to equal another table, thus unfindable.


local newData = table.clone(data)
newData.x = x
newData.y = y

Use table.clone! Assigning/declaring a variable with a table will give you a reference. Here is an example of the difference between references and copies. Strings, numbers, and booleans can be copied; Tables and Instances are referenced

-- base type copy
local old_number: number = 100
local new_number: number = old_number
print(old_number, new_number) -- 100, 100

-- changing the new_number keeps the old
new_number = 50
print(old_number, new_number) -- 100, 50


-- table type reference
local old_table: {number} = {100, 80, 95}
local new_table: {number} = old_table
print(old_table[1], new_table[1]) -- 100, 100

-- changing the new table also changes the old
new_table[1] = 50
print(old_table[1], new_table[1]) -- 50, 50
1 Like

Thank you! I have fixed my script and it looks like it works.

For if table.find(tilesTaken, {x = data.x, y = data.y}), I am now using
if table.find(tilesTaken, data.x..", "..data.y)

1 Like