Here's an updated script that adds new biomes and improves the terrain generation while maintaining the stability of the previous version:
local Terrain = game.Workspace.Terrain
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
-- Configuration
local CHUNK_SIZE = 32
local RENDER_DISTANCE = 5
local NOISE_SCALE = 0.01
local TERRAIN_SCALE = 30
local WATER_LEVEL = 1
local SEED = math.random(1, 1000000)
-- Biome Configuration
local BIOMES = {
{name = "Plains", threshold = 0.3, material = Enum.Material.Grass},
{name = "Forest", threshold = 0.5, material = Enum.Material.LeafyGrass},
{name = "Desert", threshold = 0.7, material = Enum.Material.Sand},
{name = "Snow", threshold = 0.9, material = Enum.Material.Snow},
{name = "Mountains", threshold = 1, material = Enum.Material.Rock}
}
-- Store generated chunks
local generatedChunks = {}
-- Improved noise function with seed
local function improvedNoise(x, z)
return math.noise(x * NOISE_SCALE + SEED, z * NOISE_SCALE - SEED)
end
-- Function to determine biome
local function getBiome(noise)
for _, biome in ipairs(BIOMES) do
if noise <= biome.threshold then
return biome
end
end
return BIOMES[#BIOMES]
end
-- Function to generate terrain for a single chunk
local function generateChunk(chunkX, chunkZ)
local chunkKey = chunkX .. "," .. chunkZ
if generatedChunks[chunkKey] then return end
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 noise = improvedNoise(worldX, worldZ)
local biomeNoise = improvedNoise(worldX * 0.5, worldZ * 0.5)
local biome = getBiome(biomeNoise)
local heightMultiplier = (biome.name == "Mountains") and 2 or 1
local height = math.floor((noise * TERRAIN_SCALE * heightMultiplier) + (biome.threshold * 10))
if height > WATER_LEVEL then
Terrain:FillBlock(CFrame.new(worldX, height / 2, worldZ), Vector3.new(1, height, 1), biome.material)
-- Add trees in forest biome
if biome.name == "Forest" and math.random() > 0.95 then
local treeHeight = math.random(5, 10)
Terrain:FillBlock(CFrame.new(worldX, height + treeHeight / 2, worldZ), Vector3.new(1, treeHeight, 1), Enum.Material.Wood)
Terrain:FillBlock(CFrame.new(worldX, height + treeHeight + 2, worldZ), Vector3.new(3, 4, 3), Enum.Material.LeafyGrass)
end
else
Terrain:FillBlock(CFrame.new(worldX, WATER_LEVEL / 2, worldZ), Vector3.new(1, WATER_LEVEL, 1), Enum.Material.Water)
end
end
end
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
generateChunk(chunkX + x, chunkZ + z)
end
end
end
-- Clear existing terrain
Terrain:Clear()
-- 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
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: This script maintains the stable structure of the previous version while adding new features. It should work without errors, but as always, test thoroughly in your Roblox Studio environment. The terrain generation is now more diverse and interesting, with distinct biomes and features like trees in forests.