Hello, I am attempting to make a generator that generates a grid of tiles for a planet in a game I am working on. I have had significant issues having the tiles be oriented properly when adjacent to each other. I have tried having the orientation table of valid orientations of adjacent tiles directly determine the height and orientation of surrounding tiles, aswell as having the height remain similar and subsequently orienting adjacent generated tiles after the height is decided based on surrounding tiles.
Recently, I also tried generating line by line in which each tile would check the two other tiles near it to make a list of all valid spawned tiles, and yet issues still arise. I am unsure why the tiles are not orienting in the correct direction.
Edit: I am aware this may not be enough information to help solve this issue; I can post missing information if requested. The large table with the tiles includes the valid list of tiles and their valid orientations based on the direction the tile is being spawned in, the type of tile spawning the tile, the height, and various other factors.
Sample of current generation method (I have tried like 4 or more methods)
Current generation code:
Hello, I am attempting to make a generator that generates a grid of tiles for a planet in a game I am working on. I have had significant issues having the tiles be oriented properly when adjacent to each other. I have tried having the orientation table of valid orientations of adjacent tiles directly determine the height and orientation of surrounding tiles, aswell as having the height remain similar and subsequently orienting adjacent generated tiles after the height is decided based on surrounding tiles.
Recently, I also tried generating line by line in which each tile would check the two other tiles near it to make a list of all valid spawned tiles, and yet issues still arise. I am unsure why the tiles are not orienting in the correct direction.
Sample of current generation method (I have tried like 4 or more methods)

Current generation code:
local module = {}
local tIndex = require(game.ReplicatedStorage.TerrainIndex)
local StX, StZ = math.random(1, 80), math.random(1, 80) --Starting position of the generation
local function Round(Num)
if Num >= math.floor(Num) + 0.5 then
Num = math.ceil(Num)
else
Num = math.floor(Num)
end
return Num
end
--when a part spawns rotated, compensate by having the opposite of the rotation added to the new part.
--Also note that the orientation is the y orientation
--(NameOfTile)(HeightDifference+1) = {Orientation(s) when start orientation is 0}; selects a random orientation in the table.
--Spawner table contains placed tiles tables
local OrienTable = { --Front, Right, Back, Left Directions. List of valid orientations. ex: Flat0 == -1, Flat1 == +0, Flat2 == +1
Flat = {
["0"] = {Flat1 = {0, 90, 180, -90}, Corner1 = {180, 90}, Slant1 = {90}, Slant2 = {-90}, InvertedCorner1 = {90, 180}, Point2 = {0, 90, 180, -90}, SlantCorner2 = {180}}, --Infront of
["90"] = {Flat1 = {0, 90, 180, -90}, Corner1 = {0, 90}, Slant1 = {0}, Slant2 = {180}, InvertedCorner1 = {90, 0}, Point2 = {0, 90, 180, -90}, SlantCorner2 = {180}}, --Right of
["180"] = {Flat1 = {0, 90, 180, -90}, Corner1 = {0, -90}, Slant1 = {-90}, Slant2 = {90}, InvertedCorner1 = {-90, 0}, Point2 = {0, 90, 180, -90}, SlantCorner2 = {0}}, -- Back of
["-90"] = {Flat1 = {0, 90, 180, -90}, Corner1 = {180, -90}, Slant1 = {180}, Slant2 = {0}, InvertedCorner1 = {-90, 180}, Point2 = {0, 90, 180, -90}, SlantCorner2 = {0}}}, -- Left of
Corner = {
["0"] = {Flat1 = {0, 90, 180, -90}, Corner1 = {180, 90}, Slant1 = {90}, Slant2 = {-90},InvertedCorner1 = {180, 90}, Point1 = {0, 90, 180, -90}, SlantCorner2 = {-90, 180}},
["90"] = {Flat0 = {0, 90, 180, -90}, Corner0 = {0, 90}, Slant0 = {0}, Slant1 = {180}, InvertedCorner0 = {0, 90}, Point0 = {0, 90, 180, -90}, SlantCorner1 = {90, 180}},
["180"] = {Flat0 = {0, 90, 180, -90}, Corner0 = {0, -90}, Slant0 = {-90}, Slant1 = {90}, InvertedCorner0 = {0, -90}, Point0 = {0, 90, 180, -90}, SlantCorner1 = {90, 0}},
["-90"] = {Flat1 = {0, 90, 180, -90}, Corner1 = {180 -90}, Slant1 = {180}, Slant2 = {0}, InvertedCorner1 = {180, 90}, Point1 = {0, 90, 180, -90}, SlantCorner2 = {-90, 0}}},
Slant = {
["0"] = {Slant1 = {0}, InvertedCorner1 = {0}, SlantCorner1 = {0}},
["90"] = {Flat0 = {0, 90, 180, -90}, Corner0 = {0, 90}, Slant0 = {0}, Slant1 = {180}, InvertedCorner0 = {0, 90}, Point1 = {0, 90, 180, -90}, SlantCorner1 = {0, 180}},
["180"] = {Slant1 = {0}, InvertedCorner1 = {90}, SlantCorner1 = {-90}},
["-90"] = {Flat1 = {0, 90, 180, -90}, Corner1 = {180, -90}, Slant1 = {180}, Slant2 = {0}, InvertedCorner1 = {180, -90}, Point2 = {0, 90, 180, -90}, SlantCorner2 = {0, -90}}},
InvertedCorner = {
["0"] = {Flat1 = {0, 90, 180, -90}, Corner2 = {0, -90}, Corner1 = {180, 90}, Slant2 = {-90}, Slant1 = {90}, InvertedCorner1 = {90, 180}, Point2 = {0, 90, 180, -90}, SlantCorner2 = {-90, 180}},
["90"] = {Slant1 = {-90}, InvertedCorner1 = {-90}, SlantCorner1 = {-90}},
["180"] = {Slant1 = {0}, InvertedCorner1 = {90}, SlantCorner1 = {-90}},
["-90"] = {Flat1 = {0, 90, 180, -90}, Corner2 = {0, 90}, Corner1 = {180, -90}, Slant2 = {0}, Slant1 = {180}, InvertedCorner1 = {-90, 180}, Point2 = {0, 90, 180, -90}, SlantCorner2 = {-90, 0}}},
Point = {
["0"] = {Flat0 = {0, 90, 180, -90}, Corner0 = {180, 90}, Corner2 = {0, -90}, Slant1 = {-90}, Slant0 = {90}, InvertedCorner0 = {90, 180}, Point1 = {0, 90, 180, -90}, SlantCorner1 = {180, -90}},
["90"] = {Flat0 = {0, 90, 180, -90}, Corner0 = {0, 90}, Corner2 = {180, -90}, Slant1 = {180}, Slant0 = {0}, InvertedCorner0 = {0, 90}, Point1 = {0, 90, 180, -90}, SlantCorner1 = {90, 180}},
["180"] = {Flat0 = {0, 90, 180, -90}, Corner0 = {0, -90}, Corner2 = {180, 90}, Slant1 = {90}, Slant0 = {-90}, InvertedCorner0 = {0, -90}, Point1 = {0, 90, 180, -90}, SlantCorner1 = {0, 90}},
["-90"] = {Flat0 = {0, 90, 180, -90}, Corner0 = {180, -90}, Corner2 = {0, 90}, Slant1 = {0}, Slant0 = {180}, InvertedCorner0 = {-90, 180}, Point1 = {0, 90, 180, -90}, SlantCorner1 = {-90, 0}}},
SlantCorner = {--I accidentally did these in backwards order... whoops
["0"] = {SlantCorner1 = {180, -90}, Point1 = {0, 90, 180, -90}, InvertedCorner0 = {90}, Slant0 = {90}, Slant1 = {-90}, Corner0 = {180, 90}, Flat0 = {0, 90, 180, -90}},
["90"] = {SlantCorner1 = {180, 90}, Point1 = {0, 90, 180, -90}, InvertedCorner0 = {0}, Slant0 = {0}, Slant1 = {180}, Corner0 = {0, 90}, Flat0 = {0, 90, 180, -90}},
["180"] = {SlantCorner1 = {-90}, InvertedCorner1 = {90}, Slant1 = {0}},
["-90"] = {SlantCorner1 = {90}, InvertedCorner1 = {90}, Slant1 = {90}}}
} --Table of valid tile orientations and configurations, utilizes tiles of heigh diffrence of 0-1 (also -1)
module.TGenNew = function(Biome)-- Select biome from TerrainIndex
local Biome = tIndex[Biome]
local dist = Biome.Scale
local PlacedTiles = {}
local TileFolder = Instance.new("Folder")
TileFolder.Parent = game.Workspace
TileFolder.Name = "GeneratedMap"
for x = 1, 80 do PlacedTiles[x] = {}--Sets up the matrix
for z = 1, 80 do
PlacedTiles[x][z] = 0--AvailableTiles[math.random(1, #AvailableTiles)][math.random(1,4)]
end
end
local a = {-1, 0, 1}
local b = {-1, 1}
local NewHeight2 = math.random(1,4)
for v = 1, 80 do -- V = X, B = Z
for b = 1, 80 do
local function nextTile()-- Going right / 90° increases X, and going back/ 180° increases Z.
local TileTypes = {"Flat", "Corner", "Slant", "InvertedCorner", "Point", "SlantCorner"}
local TV
local TB
if v-1 ~= 0 and PlacedTiles[v-1] then
TV = PlacedTiles[v-1][b]
end
if b-1 ~= 0 then
TB = PlacedTiles[v][b-1]
end
if not TV and not TB then return game.Workspace.Tiles.BasicTiles.Flat[NewHeight2.."Flat"][NewHeight2.."Flat1"] end
local TVType--Tile type of the last tile made in the X direction
local TBType--Tile type of the last tile made in the Z direction
local TVOrien --Orientation of the last tile made in the X direction
local TBOrien --Orientation of the last tile made in the Z direction
local TVHeight --Height of the last tile made in the X direction
local TBHeight--Height of the last tile made in the Z direction
local NumberToSatisfy = 2
local DV = 90--Base Direction that tiles are spawned in on the X-Axis
local DB = 180--Base Direction that tiles are spawned in on the Z-Axis
local GoodTiles = {}
if TV then
TVType = string.sub(TV.Name, 2, -2)
TVOrien = TV.PrimaryPart.Orientation
TVHeight = string.sub(TV.Name, 1, 1)
DV += TVOrien.Y
if DV >= 270 then DV = DV -360 elseif DV <-90 then DV += 360 end
if DV == -90 then DV = "-90" else DV = tostring(DV) end
end
if TB then
TBType = string.sub(TB.Name, 2, -2)
TBOrien = TB.PrimaryPart.Orientation
TBHeight = string.sub(TB.Name, 1, 1)
DB += TBOrien.Y
if DB >= 270 then DB = DB -360 elseif DB <-90 then DB += 360 end
if DB == -90 then DB = "-90" else DB = tostring(DB) end
end
if not TV or not TB then NumberToSatisfy = 1 end
for x, c in pairs({0, 1, 2}) do
for z, d in pairs(TileTypes) do
local Tester = d..c
if NumberToSatisfy == 2 then
if OrienTable[TVType][DV][Tester] and OrienTable[TBType][DB][Tester] and not (c-1+TVHeight < 0) and (not (c-1+TVHeight < 1 and d ~= "Flat")) and not (c-1+TVHeight > 5) and not (c-1+TBHeight < 0) and (not (c-1+TBHeight < 1 and d ~= "Flat")) and not (c-1+TBHeight > 5) then
GoodTiles[Tester] = OrienTable[TVType][DV][Tester]
end
elseif TV then
if OrienTable[TVType][DV][Tester] and not (c-1+TVHeight < 0) and (not (c-1+TVHeight < 1 and d ~= "Flat")) and not (c-1+TVHeight > 5) then
GoodTiles[Tester] = OrienTable[TVType][DV][Tester]
end
elseif TB then
if OrienTable[TBType][DB][Tester] and not (c-1+TBHeight < 0) and (not (c-1+TBHeight < 1 and d ~= "Flat")) and not (c-1+TBHeight > 5) then
GoodTiles[Tester] = OrienTable[TBType][DB][Tester]
end
end
end
end
local SelectedTile = {}
local totalCount = 0
for i, v in pairs(GoodTiles) do totalCount = totalCount + 1 end
if totalCount == 0 then
return game.Workspace.Tiles.BasicTiles.Flat[NewHeight2.."Flat"][NewHeight2.."Flat1"]
end
local ranTN = math.random(1, totalCount)
local testCount2 = 0
for i, v in pairs(GoodTiles) do
testCount2 = testCount2 + 1
if testCount2 == ranTN then
SelectedTile["Tile"] = tostring((tonumber(string.sub(i, -1, -1))-1)+(TVHeight or TBHeight))..string.sub(i, 1, -2)
SelectedTile["Orientation"] = v[math.random(1, #v)]
end
end
local nTileFold = game.Workspace.Tiles.BasicTiles[string.sub(SelectedTile["Tile"], 2, -1)][SelectedTile["Tile"]]
local which = math.random(1,4)
local Tile, Ori = nTileFold[SelectedTile["Tile"]..which], SelectedTile["Orientation"]
return Tile, Ori
end
local NewTile, NOri = nextTile()
NewTile = NewTile:Clone()
PlacedTiles[v][b] = NewTile
NewTile.Parent = TileFolder
NewTile:PivotTo(CFrame.new(Vector3.new((v)*100-4000, 10 ,(b)*100-4000))*CFrame.Angles(0, math.rad(NOri or 90), 0))
PlacedTiles[v][b] = NewTile
for i, v in pairs(PlacedTiles[v][b]:GetDescendants()) do
if v.Name == "BASE" then
v.Color = Biome.Base.Color
v.Material = Biome.Base.Material
if Biome.Base.MaterialVariant ~= nil then
v.MaterialVariant = Biome.Base.MaterialVariant
end
elseif v.Name ~= "DepositSpawn" and v.Name ~= "FoliageSpawn" and v.Name ~= "EnemySpawn" then
v.Color = Biome.Top.Color
v.Material = Biome.Top.Material
if Biome.Top.MaterialVariant ~= nil then
v.MaterialVariant = Biome.Top.MaterialVariant
end
end
end
end
end
end
return module

