I have a basic script that allows for a given width and height of cubes, and for the baseplate size. Now what I was wondering is how to smooth the slopes, rather than using math.random to give me random heights.
local width = 2 local height = 2 local baseplate = {30, 30} local model = Instance.new("Model") model.Parent = game.Workspace model.Name = "Terrain Parts" local bricksRemove = game.Workspace:FindFirstChild("Terrain Parts"):GetChildren() for num, obj in pairs(bricksRemove)do if obj:IsA("Part") then if obj.Name == "Terrain Blocks" then obj:Destroy() end end end for i = 0, ((baseplate[1]/width)*(baseplate[2]/width))-1 do local brick = Instance.new("Part") brick.FormFactor = 3 brick.Size = Vector3.new(width, height, width) brick.Position = Vector3.new((i%(baseplate[1]/width))*width, math.random()+4, math.floor(i/(baseplate[2]/width))*2) brick.Anchored = true brick.Name = "Terrain Blocks" brick.Parent = game.Workspace:FindFirstChild("Terrain Parts") end
I was debating whether getting blocks at certain intervals and using them to decide the incline/decline then smooth the blocks within a given range to that, but that didn't seem efficient. So if anyone has any information that will guide me into making smooth terrain, I would be grateful.
~ Legobuildermaster
First, you should simplify this code a little.
Clearing the children can be much simpler:
* There's no point to :FindFirstChild
if you immediately call :GetChildren
* You shouldn't have the space in the name in the first place.
* You should just use ["Terrain Parts"]
if you insist on having the space
* You can combine the two if
s using and
to save two lines and a level of indentation
* No need to use a name like num
if you aren't going to use it
* You should use workspace
instead of game.Workspace
* You should probably use "TerrainBlock" instead of "Terrain Blocks"
* each is one Block; each is not several Blocks
* it's not normal for names to have spaces in them
for _, child in pairs(workspace.TerrainParts:GetChildren()) do if child:IsA("BasePart") and child.Name == "Terrain Blocks" then child:Destroy() end end
You can iterate over the grid much more easily, too. You don't need i
itself, you just need the x
and y
. I would recommend not using baseplate
or width
or height
because the names are very unclear. I would recommend blockWidth
and blockHeight
to describe sizes of individual blocks and worldX
and worldZ
or similar to describe the size of the world.
It's also easier to talk about x
and y
for x = 0, worldX, blockWidth do for z = 0, worldZ, blockWidth do local brick = Instance.new("Part") brick.FormFactor = "Custom" -- Use descriptive values!! brick.Anchored = true brick.Size = Vector3.new(blockWidth, blockHeight, blockWidth) local y = math.random() * 4 brick.Position = Vector3.new(x, y, z) brick.Name = "TerrainBlock" brick.Parent = workspace.TerrainParts end end
Now, you need y
to just be a function of x
and z
.
There are tons of different ways to do terrain generation. Recently ROBLOX added math.noise
which gives you access to Perlin noise. You could use it something like this:
function height(x, y) return (math.noise(x / 20, y / 20) + math.noise(x / 35, y / 35) + math.noise(x / 77, y / 77)) * 10 end .... local y = height(x, z) brick.Position = Vector3.new(x, y, z) ....