¿How can i achieve making craters on hollow (thin) terrain?

If you didn’t understand by the title, let me explain via this image:


What i want to achieve here is to make a Erode tool similar to roblox’s to make craters via script for my terrain generator that wont just delete all voxels around, but roblox’s Erode tool just deletes smoothly the voxels around it and and leaves air behind.

I tried using ReadVoxels() and & WriteVoxels() but i can’t think of a way of doing this properly.

So, is there a way to make this?

PS: I wont change the width of my terrain since it will affect performance

1 Like

As for the post: I don’t have any code for you, but you could procedurally generate voxels around the zone of the tool. Since you have air above and below, the challenge will be determining whether the empty voxel should be filled with terrain or remain empty (air). One straightforward method would be raycasting from the tool to each potential edge cell. If it the ray hits terrain, fill that cell with the same material.

2 Likes

Not Exactly, You can do this without a script

But this may help:

  • Add 2 Balls Insider of each other and create a union, you should be able to Change the shape of it now, (Actually doesn’t work, but it still creates a crater, So just use a Regular ball)

  • Add this Code:

workspace.Terrain:FillBall(script.Parent.Position, 30, Enum.Material.Air)
--For Center, just put its position
--For Radius, Put the X, or Z number (Its Size) or just whatever you like
-- Put the Material as "Air" to delete the Material Below
script.Parent:Destroy() -- Deletes the Part

This is the end Result: (Based on Where I put it)


The Changes Depend on where the Hitbox and Center is located, That’s why there isn’t much of a change here
So now i made it look like this:

I Hope this helps

To improve Performance, its better to add Parts that will fill the Terrain when the game starts

1 Like

@iPeeDev I made an Update, this should do it:
(Once again, based on where you put it)

workspace.Terrain:FillBall(script.Parent.Position + Vector3.new(0,-3,0), script.Parent.Size.X, Enum.Material.Ground) -- Creates the Outline for the Crater
workspace.Terrain:FillBall(script.Parent.Position, script.Parent.Size.X, Enum.Material.Air)
script.Parent:Destroy() 

You can always change its Radius by Adding or subtracting script.Parent.Size.X

1 Like

Dunno if someone is for some reason searching this topic, but i managed to make this work:

local Position = workspace.Part.Position
local Size = workspace.Part:GetAttribute("Size")

local Filtered = {}
local Region = Region3.new(
	Position - (Vector3.one * Size / 2),
	Position + (Vector3.one * Size / 2)
)

local Materials, Occupancies = workspace.Terrain:ReadVoxels(Region,4)

function returnMaterial(tab, x, z)
	local y = 0
	repeat 
		y += 1
	until tab[("%s,%s,%s"):format(x,y,z)]
	return tab[("%s,%s,%s"):format(x,y,z)]
end

for x = 1,Materials.Size.X do
	for y = 1,Materials.Size.Y do
		for z = 1,Materials.Size.Z do 
			if Materials[x][y][z] ~= Enum.Material.Air then
				for yy = y,Size do
					Filtered[("%s,%s,%s"):format(x,yy,z)] = true	
				end
			end
		end
	end
end

local Middle = Vector3.new(
	Materials.Size.X / 2,
	Materials.Size.Y / 2,
	Materials.Size.Z / 2
)
local Max = Vector3.new(
	Materials.Size.X,
	Materials.Size.Y,
	Materials.Size.Z
).Magnitude / 2

for y = 1,Materials.Size.X do
	for x = 1,Materials.Size.Y do
		for z = 1,Materials.Size.Z do 
			local Distance = (Vector3.new(x,y,z) - Middle).Magnitude
			if Distance / Max < 0.4 then
				Materials[x][y][z] = Enum.Material.Air
				Occupancies[x][y][z] = 0
			end

			if Filtered[("%s,%s,%s"):format(x,y,z)] ~= true then
				if Distance / Max < 0.5 then
					Materials[x][y][z] = returnMaterial(Materials,x,z)
					Occupancies[x][y][z] = 1
				end
			end
		end
	end
	task.wait()
end

workspace.Terrain:WriteVoxels(Region,4,Materials,Occupancies)
1 Like