Here's an updated Lua script that incorporates multiple biomes (including snow and desert), mountains, a seed system, and performance optimizations:
-- Advanced Terrain Generation Script with Biomes
local Terrain = game.Workspace.Terrain
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
-- Configuration
local CHUNK_SIZE = 16
local RENDER_DISTANCE = 5
local MAX_HEIGHT = 100
local NOISE_SCALE = 0.005
local BIOME_SCALE = 0.001
local MOUNTAIN_SCALE = 0.002
local SEED = math.random(1, 1000000) -- Random seed, change as needed
-- Store generated chunks
local generatedChunks = {}
-- Biome definitions
local BIOMES = {
PLAINS = {
threshold = 0.3,
baseHeight = 10,
materials = {Enum.Material.Grass, Enum.Material.Sand, Enum.Material.Rock}
},
DESERT = {
threshold = 0.6,
baseHeight = 5,
materials = {Enum.Material.Sand, Enum.Material.Sand, Enum.Material.Sandstone}
},
SNOW = {
threshold = 0.9,
baseHeight = 15,
materials = {Enum.Material.Snow, Enum.Material.Snow, Enum.Material.Ice}
},
MOUNTAINS = {
threshold = 1.0,
baseHeight = 30,
materials = {Enum.Material.Rock, Enum.Material.Rock, Enum.Material.Slate}
}
}
-- Improved noise function with seed
local function improvedNoise(x, y, z)
return math.noise(x + SEED, y - SEED, z + SEED)
end
-- Function to get biome based on position
local function getBiome(x, z)
local biomeNoise = improvedNoise(x * BIOME_SCALE, 0, z * BIOME_SCALE)
for biomeName, biomeData in pairs(BIOMES) do
if biomeNoise <= biomeData.threshold then
return biomeName, biomeData
end
end
return "PLAINS", BIOMES.PLAINS -- Default to plains
end
-- Function to generate height using improved noise
local function getTerrainHeight(x, z)
local biomeName, biomeData = getBiome(x, z)
local baseHeight = biomeData.baseHeight
local terrainNoise = improvedNoise(x * NOISE_SCALE, 0, z * NOISE_SCALE)
local mountainNoise = improvedNoise(x * MOUNTAIN_SCALE, 0, z * MOUNTAIN_SCALE)
local height = baseHeight + terrainNoise * 20
if biomeName == "MOUNTAINS" then
height = height + mountainNoise * 50
end
return math.floor(math.clamp(height, 1, MAX_HEIGHT))
end
-- Function to create terrain for a single chunk
local function createChunk(chunkX, chunkZ)
local chunkKey = chunkX .. "," .. chunkZ
if generatedChunks[chunkKey] then return end
local terrainRegion = Region3.new(
Vector3.new(chunkX * CHUNK_SIZE, 0, chunkZ * CHUNK_SIZE),
Vector3.new((chunkX + 1) * CHUNK_SIZE - 1, MAX_HEIGHT, (chunkZ + 1) * CHUNK_SIZE - 1)
)
local materials = {}
local occupancy = {}
for x = 0, CHUNK_SIZE - 1 do
for z = 0, CHUNK_SIZE - 1 do
local worldX = chunkX * CHUNK_SIZE + x
local worldZ = chunkZ * CHUNK_SIZE + z
local height = getTerrainHeight(worldX, worldZ)
local _, biomeData = getBiome(worldX, worldZ)
for y = 0, height do
local index = x + 1 + (z * CHUNK_SIZE) + (y * CHUNK_SIZE * CHUNK_SIZE)
local material
if y == height then
material = biomeData.materials[1]
elseif y > height - 3 then
material = biomeData.materials[2]
else
material = biomeData.materials[3]
end
materials[index] = material
occupancy[index] = 1
end
end
end
Terrain:WriteVoxels(terrainRegion, CHUNK_SIZE, CHUNK_SIZE, CHUNK_SIZE, materials, occupancy)
generatedChunks[chunkKey] = true
end
-- Function to update terrain around the player
local function updateTerrain(player)
local character = player.Character
if not character then return end
local position = character.PrimaryPart.Position
local chunkX = math.floor(position.X / CHUNK_SIZE)
local chunkZ = math.floor(position.Z / CHUNK_SIZE)
for x = -RENDER_DISTANCE, RENDER_DISTANCE do
for z = -RENDER_DISTANCE, RENDER_DISTANCE do
createChunk(chunkX + x, chunkZ + z)
end
end
end
-- Update terrain when a player's character spawns
Players.PlayerAdded:Connect(function(player)
player.CharacterAdded:Connect(function(character)
wait(1)
updateTerrain(player)
end)
end)
-- Continuously update terrain as players move
local lastUpdate = 0
local UPDATE_INTERVAL = 0.5 -- Update every 0.5 seconds
RunService.Heartbeat:Connect(function(deltaTime)
lastUpdate = lastUpdate + deltaTime
if lastUpdate >= UPDATE_INTERVAL then
for _, player in ipairs(Players:GetPlayers()) do
updateTerrain(player)
end
lastUpdate = 0
end
end)
Note: While this script includes several optimizations, very large worlds or many simultaneous players may still impact performance. For production games, consider implementing additional optimizations such as multi-threading, custom mesh generation, or server-side terrain generation.