the grass is generating like this, but I want it replaced by dirt blocks alredy within a folder in my game, How can I generate it?
I searched in google, youtube and inside the forum, and found nothing
local BLOCK_SIZE = 3.054
local MAP_SIZE = Vector3.new(150, 64, 150)
local MOUNTAIN_INTENSITY = 8
local function PlantTree()
end
seed = workspace.SEED.Value
noisescale = 1/64
amplitude = 10
function get_density(v3)
local noise_value = math.noise(v3.X * noisescale, v3.Y * noisescale, v3.Z * noisescale + seed)*amplitude
local height_bonus = -v3.Y / MOUNTAIN_INTENSITY + 8
return noise_value + height_bonus
end
function is_on_boundary(v3)
if get_density(v3) <= 0 then
return false
end
for _, dirEnum in pairs(Enum.NormalId:GetEnumItems()) do
local dir = Vector3.FromNormalId(dirEnum)
local neighbor_pos = v3 + dir * BLOCK_SIZE
local neighbor_density = get_density(neighbor_pos)
if neighbor_density <= 0 then
return true
end
end
return false
end
for x = 0, MAP_SIZE.X do
for y = 0, MAP_SIZE.Y do
for z = 0, MAP_SIZE.Z do
local block_pos = Vector3.new(x, y, z) * BLOCK_SIZE
local density = get_density(block_pos)
if density > 0 and is_on_boundary(block_pos) then
local block = script.Block:Clone()
block.Parent = game.Workspace
block.CFrame = CFrame.new(block_pos)
if y > 25 then
local c = game.ReplicatedStorage.Blocks.Nature.Snow:Clone()
c:SetPrimaryPartCFrame(block.CFrame)
c.Parent = workspace.TerrainFolder
block:Destroy()
elseif y < 23 and y > 1 then
local c = game.ReplicatedStorage.Blocks.Nature.Grass:Clone()
c:SetPrimaryPartCFrame(block.CFrame)
c.Parent = workspace.TerrainFolder
block:Destroy()
local trees = game.ReplicatedStorage.Structures.Trees:GetChildren()
if math.random(1, 100) == 1 then
local tree = trees[math.random(1, #trees)]:Clone()
tree.Parent = workspace.TerrainFolder.Trees
tree:SetPrimaryPartCFrame(c.PrimaryPart.CFrame)
end
elseif y <= 1 then
local c = game.ReplicatedStorage.Blocks.Nature.Sand:Clone()
c:SetPrimaryPartCFrame(block.CFrame)
c.Parent = workspace.TerrainFolder
block:Destroy()
else
local c = game.ReplicatedStorage.Blocks.Nature.Stone:Clone()
c:SetPrimaryPartCFrame(block.CFrame)
c.Parent = workspace.TerrainFolder
block:Destroy()
end
end
end
end
wait(0.2)
end
I forgot to mention, I also implemented a function where I generate trees on top of grass blocks, but you think that I can make the tree smaller? WRONG because it’s an entire model!
I don’t understand how a Raycast would help. Your code seems to create blocks on lower y coordinates before higher, so even if a block was going to be placed above the block you are placing, that block would not be there yet. So if you casted a ray upwards from the position of the current block, the ray would hit nothing.
Raycasts can only be 5000 studs long, you would only need to raycast BLOCK_SIZE studs up anyway, and @RoBoPoJu’s approach is probably more performant anyway and more flexible IMO.
Raycasting upwards makes a lot of sense. But like RoBoPoJu mentioned, you’ll have to make sure that you generate everything from the top of the world to the bottom, otherwise there won’t be anything to detect with the ray. Or you can do it in two passes, placing grass everywhere initially and then looping over every placed block, raycasting upwards to see if there’s anything above.Or you could store every block that doesn’t have anything above it in a table and only check those in the second pass.
local hit = workspace:Raycast(Vector3.new(c.Grass.CFrame.X,c.Grass.CFrame.Y + 1,c.Grass.CFrame.Z), Vector3.new(c.Grass.CFrame.X,c.Grass.CFrame.Y + 100,c.Grass.CFrame.Z))
for i, hit in pairs(???) do
What you get back as a return value from :Raycast() is a RaycastResult, you can read more about that on the wiki. Short explanation is that if you get a RaycastResult, you can check what it hit by checking result.Instance. If it hit a block on its way up, don’t make it into grass.