I am currently making a procedural terrain generator for a game I am work on, and I have made a primitive version of the procedural terrain generator. However, I want the terrain to be (mostly) smooth, with slopes that fit nicely with eachother, along with rivers, and other special terrain. The generator will also have variables such as “smoothness” (how many or little sudden drops and rough terrain there will be), and flatness (how much vertical height there will be.) Also, it can adapt to generate different types of terrain by veiwing attributes of parts and terrain-type folders. Here are some current basic terrain generation, where each part has random orientation (so the smoothness variable is basically non-existant), and water generation (i plan to make random rivers and lakes) hasnt been figrured out, nor has any vertical aspect.
Pictures of current terrain generation:
Current terrain gen code:
folder = Instance.new("Folder")
folder.Name = "MapTerrain"
folder.Parent =game.Workspace
local TotalRarity = 0
local ChanceTable = {}
local TotalTiles = 0
local debris = game:GetService("Debris")
local TerrainType = game.Workspace.Hills --change the folder to change the map type
local FlatTilePreset = TerrainType.BasicTiles.Flat
function SortByRarity(RarityTable, ObjectTable)
RarityTable = RarityTable or {}
for i, v in pairs(ObjectTable) do
local rar = v:GetAttribute("RarityWeight")
if rar ~= nil then
TotalRarity += rar
table.insert(RarityTable, {Rarity = TotalRarity, Object = v})
end
end
table.sort(ChanceTable, function(a, b)
if a.Rarity < b.Rarity then
return true
end
return false
end)
return RarityTable
end
SortByRarity(ChanceTable, TerrainType:GetDescendants())
function SelectPart()
local PartRan = math.random(0, TotalRarity)
local PartSelected
local PreviousStep = 0
for i, v in pairs(ChanceTable) do
if PartRan >= PreviousStep and PartRan <= v.Rarity then
PartSelected = v.Object
return PartSelected
end
PreviousStep = v.Rarity
end
end
function SpawnAdjacentTiles(CenterTile)
if TotalTiles >= 6500 then return end
local OriginalPos
if CenterTile ~= nil then
if CenterTile:IsA("Model") then
OriginalPos = CenterTile.PrimaryPart.Position
else
OriginalPos = CenterTile.Position
end
if math.abs(OriginalPos.X) >= 4000 or math.abs(OriginalPos.Z) >= 4000 then return end
else
OriginalPos = Vector3.new(50, 0, 50)
end
for i = 1, 4 do
local x
local z
if i == 1 then x = 1 z = 0 elseif i == 2 then x =0 z = 1 elseif i == 3 then x = -1 z = 0 else x = 0 z = -1 end
local Tile = SelectPart():Clone()
local special = false
local params = RaycastParams.new()
params.FilterDescendantsInstances = {folder, Tile}
params.FilterType = Enum.RaycastFilterType.Include
local rayRes = workspace:Raycast(OriginalPos, Vector3.new((x * 100), 0, (z*100)), params)
if Tile:GetAttribute("SpecialTile") == true then
special = true
end
Tile.Parent = folder
local Rotation = math.random(1, 4)
Rotation*=90
Rotation *= math.pi/180
if rayRes == nil then
if Tile:IsA("Model") then
Tile:PivotTo(CFrame.new(Vector3.new(OriginalPos.X + (x * 100), 12.5*5, OriginalPos.Z + (z*100)))*CFrame.Angles(0, Rotation, 0))
else
Tile.CFrame = CFrame.new(Vector3.new(OriginalPos.X + (x * 100), 12.5*5, OriginalPos.Z + (z*100)))*CFrame.Angles(0, Rotation, 0)
end
task.defer(function()
SpawnAdjacentTiles(Tile)
end)
TotalTiles += 1
else
Tile:Destroy()
end
end
end
--[[for x = 1, 80 do --Spawns flat preset
for z = 1, 80 do
local Tile = FlatTilePreset:Clone()
local Rotation = math.random(1, 4)
Rotation*=90
Rotation *= math.pi/180
if Tile:IsA("Model") then
Tile:PivotTo(CFrame.new(Vector3.new((x*100)-4050, 12.5*5, (z*100)-4050))*CFrame.Angles(0, Rotation, 0))
Tile.Parent = folder
else
Tile.CFrame = CFrame.new(Vector3.new((x*100)-4050, 12.5*5, (z*100)-4050))*CFrame.Angles(0, Rotation, 0)
Tile.Parent = folder
end
end
end--]]
function SpawnWater()
end
SpawnAdjacentTiles()
Note that the generator uses various rarity and slope attributes to determine frequency and location of parts (though the slope part is unfinished). My current idea is generating a flat baseplate of tiles, then adding features like sloped parts, special tile parts (lake and hill models), rivers and lakes (not special tile models), and verticallity. Also note that the special tiles aren’t completly neccesary, and could be added after basic terrain generation (I am making this to greatly simplify terrain generation for a game, as opposed to manually making tons of planet terrain.)