I’m making a random map generator and i needed help with finding the first layer of my map (see below) to know which parts are grass, which are dirt, stone, etc.

I have tried to color the parts by their position on the Y axis but am not proud of the results.

local MAP_SIZE_X = 64
local MAP_SIZE_Y = 32
local MAP_SIZE_Z = 64
local SEED = 0
local NOISE_SCALE = 30
local AMPLITUDE = 20
local BLOCK_SIZE = 4
if workspace.SEED.Value == 0 then
SEED = math.random(0, 1000000)
workspace.SEED.Value = SEED
else
SEED = workspace.SEED.Value
end
for x = 0, MAP_SIZE_X do
for z = 0, MAP_SIZE_Z do
for y = 0, MAP_SIZE_Y do
local X_NOISE = math.noise(y/NOISE_SCALE, z/NOISE_SCALE, SEED) * AMPLITUDE
local Y_NOISE = math.noise(x/NOISE_SCALE, z/NOISE_SCALE, SEED) * AMPLITUDE
local Z_NOISE = math.noise(x/NOISE_SCALE, y/NOISE_SCALE, SEED) * AMPLITUDE
local DENSITY = X_NOISE + Y_NOISE + Z_NOISE + y
if DENSITY < 10 and DENSITY > 0 then
local part = Instance.new("Part", workspace.TerrainFolder)
part.Anchored = true
part.Material = Enum.Material.SmoothPlastic
part.Size = Vector3.new(BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE)
part.CFrame = CFrame.new(x*BLOCK_SIZE, y*BLOCK_SIZE, z*BLOCK_SIZE)
end
end
end
wait()
end

When I was testing out your map generation script…and I noticed…if a block is on top of another one, it will always be 4 studs above it.

You can create another loop that loops through all the parts inside the folder and use Ray Casting to check if there’s a part that’s 4 studs above it. If there’s not a part above it by 4 studs…the script will consider it a top layer.

In this script below…it does just that and for every part considered a top layer…it turns it green (plus is has the fixes I recommended before):

local MAP_SIZE_X = 64
local MAP_SIZE_Y = 32
local MAP_SIZE_Z = 64
local SEED = 0
local NOISE_SCALE = 30
local AMPLITUDE = 20
local BLOCK_SIZE = 4
if workspace.SEED.Value == 0 then
SEED = math.random(0, 1000000)
workspace.SEED.Value = SEED
else
SEED = workspace.SEED.Value
end
for x = 0, MAP_SIZE_X do
for z = 0, MAP_SIZE_Z do
for y = 0, MAP_SIZE_Y do
local X_NOISE = math.noise(y/NOISE_SCALE, z/NOISE_SCALE, SEED) * AMPLITUDE
local Y_NOISE = math.noise(x/NOISE_SCALE, z/NOISE_SCALE, SEED) * AMPLITUDE
local Z_NOISE = math.noise(x/NOISE_SCALE, y/NOISE_SCALE, SEED) * AMPLITUDE
local DENSITY = X_NOISE + Y_NOISE + Z_NOISE + y
if DENSITY < 10 and DENSITY > 0 then
local part = Instance.new("Part")
part.Parent = workspace.TerrainFolder
part.Anchored = true
part.Material = Enum.Material.SmoothPlastic
part.Size = Vector3.new(BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE)
part.CFrame = CFrame.new(x*BLOCK_SIZE, y*BLOCK_SIZE, z*BLOCK_SIZE)
end
end
end
task.wait()
end
for i, v in pairs(workspace.TerrainFolder:GetChildren()) do
local MapPartParams = RaycastParams.new()
MapPartParams.FilterDescendantsInstances = {v}
MapPartParams.FilterType = Enum.RaycastFilterType.Blacklist
local PartAbove = workspace:Raycast(v.CFrame.p,Vector3.new(0,4,0),MapPartParams)
if not PartAbove then
v.Color = Color3.new(0, 1, 0)
else
print("Layer detected above the part")
end
task.wait()
end

Cache all the blocks in the table, then insert whatever arguments you want into each individual table, which can be accessed by providing the x, y and z coordinates:

local partCache = {}
partCache[x][z][y1] = Part
partCache[x][z][y2] = Part
partCache[x][z][y3] = Part
--// Using your code
for x = 0, MAP_SIZE_X do
for z = 0, MAP_SIZE_Z do
for y = 0, MAP_SIZE_Y do
--code
local part = Instance.new("Part")
partCache[x][z][y] = part
--code
end
end
end

Then you’d get the x and z coordinates of the positions and get the highest y value from the table:

for _, xTable in pairs(cache) do -- Looping through the part caches in each x coordinate
for _, zTable in pairs(xTable) do -- Looping through the part xCache in each z coordinate
local maxY = 0 -- Make sure this variable is smaller or equal to the hight minimum
for y in pairs(zTable) do -- Looping through the zTable for each y coordinate
if y > maxY then -- Checking if the y level of this part is bigger than the previous
maxY = y -- Setting the y level
end
end
zTable[y].Color = Color3.fromRGB(0, 0, 0) -- Setting the colour
end
end